1. Чому замок і що є заблокованим?
Коли ми використовуємо потоки, найефективніший спосіб, звісно, асинхронний, тобто кожен потік працює одночасно, без залежності один від одного і очікування. Однак, коли різні потоки потребують доступу до певного ресурсу, потрібен механізм синхронізації, тобто при читанні та записі одного й того ж ресурсу потрібно зробити так, щоб ресурс одночасно керувався лише одним потоком, щоб кожна операція була ефективною та негайною, тобто щоб забезпечити атомарність її роботи. lock є найпоширенішим методом синхронізації в C#, у форматі lock(objectA){codeB}.
lock(objectA){codeB} здається простим, але насправді має три значення, що є необхідним для правильного використання: 1. Чи заблоковано об'єктА? Якщо ні, я заблокую його, інакше чекаю, поки буде звільнено objectA. 2. Після блокування інші потоки не можуть викликати codeB або використовувати objectA під час виконання codeB. 3. Після виконання codeB можна відпустити objectA, і codeB можуть отримати доступ для інших потоків.
2. Що сталося з замком (цим)?
Розглянемо приклад:
У потоці t1 LockMe викликає lock(this), тобто c1 у головній функції, і при виклику lock(c1) у головному потоці має чекати, поки блок блокування в t1 буде виконано, перш ніж звертатися до c1, тобто всі операції, пов'язані з c1, не можуть бути виконані, тому ми бачимо, що навіть c1. DoNotLockMe() не виконується.
|