Поширені сценарії неправильного використання: щоб запобігти повторюванню оплати замовлень, спричинених випадковим натисканням кнопки оплати користувачами кілька разів, ми використовуємо блокування (номер замовлення), щоб гарантувати, що операцію може виконувати лише один потік.
Ця ідея хороша, принаймні краща за блокування (приватний статичний об'єкт для класів обробки), оскільки ефект блокування номера порядку полягає в тому, що блокування лише поточного порядку 1, і якщо блокування статичної змінної, тобто блокування всіх нарядів, це призведе до того, що всі замовлення будуть поставлені в чергу, що, очевидно, є нерозумним.
Отже, чи може метод замка (номер замовлення), згаданий на початку цієї статті, досягти бажаного ефекту? Спочатку використаємо код, щоб відновити сценарій використання.
Якщо ігнорувати інформацію користувача та інші перевірки, код виглядає приблизно так:
Для ключового слова блокування MSDN містить інформацію, яку можна знайти на Baidu, і, здається, рекомендується не використовувати lock(string), і причина така сама. Наступний уривок взято з порад MSDN щодо замкових струн:
Проблема з блокуванням («myLock») виникає тому, що будь-який інший код, що використовує той самий рядок у процесі, матиме той самий блок. Це речення приховує величезний механізм, тобто «ту саму нитку».
Що таке «одна й та сама нитка»? Дивіться код:
Чи є str1 і str2 одним і тим самим рядком вище? Відповідь — ТАК.
Дивіться ще раз:
Чи str1 і str2 вище залишаються тими ж струнами? Відповідь — НІ.
Добре, повернемося до питання оплати замовлення. У нашому коді, lock(orderNumber), коли користувач випадково натискає ще кілька разів після проведення руки, чи вводить orderNumber цю дію тим самим рядком щоразу? Відповідь — НІ. Тобто,
Код, який обробляє наведене вище замовлення, фактично не виконує функції блокування.
Насправді існує два типи порівнянь рядків, див. код:
Перший рядок наведеного вище коду видає True, а другий рядок — False. Гадаю, ви розумієте, що MSDN має на увазі під «той самий рядок» без мого пояснення.
Найкраще рішення
Рішення для оптимальних блокувальних струн:
Демо-код:
На вебсайті іноді може використовуватися глобальна змінна, яка при одночасному доступі кількох користувачів може виглядати ненормально, тоді ми встановлюємо глобальне блокування, але недоліком цього є те, що всі доступи чекатимуть по черзі.
У деяких ситуаціях, наприклад, один і той самий користувач може коментувати лише один раз протягом 15 секунд, якщо використовується глобальне блокування, функція коментаря буде дуже повільно оброблятися при зростанні кількості користувачів, що суттєво впливає на користувацький досвід.
У цей час,Ми можемо встановити блокування для кожного користувача окремо, lock(string){...}, а ім'я блокування можна визначити так:Ім'я методу + ідентифікатор користувачаТаким чином, кожен користувач має незалежне блокування, і при оцінці інтервалу коментарів це не впливає на коментарі інших користувачів.
(Кінець)
|