#net #многопоточность
При попытке снять блокировку монитора из другого потока выбрасывается исключение An unhandled exception of type 'System.Threading.SynchronizationLockException' occurred in Test - Smth.exe Additional information: Для не синхронизированного блока кода вызван метод синхронизации объектов. Пример кода: Imports System.Threading Module All Sub Main() Dim Obj As New Object Monitor.Enter(Obj) Call (New Thread(Sub() Monitor.Exit(Obj))).Start() Console.ReadKey() End Sub End Module Возможно ли как-то снять блокировку из того потока, который её НЕ устанавливал?
Ответы
Ответ 1
С монитором — нет, никак. Насколько я понимаю, единственный синхронизационный примитив, который позволяет разблокировать себя из другого потока — это Semaphore (лучше брать рекомендованный вариант SemaphoreSlim). Пример (на C#) var sema = new SemaphoreSlim(0); // создаём заблокированный семафор new Thread(() => { sema.Release(); // разблокируем его // ... }).Start(); sema.Wait(); // ожидаем разблокировки Если вы хотите просто дождаться реального старта другого потока, можно использовать ManualResetEventSlim. Код практически такой же: var ev = new ManualResetEventSlim(initialState: false); new Thread(() => { ev.Set(); // ... }).Start(); ev.Wait(); Поправка: всё-таки исходную проблему можно решить с монитором, если заставить его работать как conditional variable. Код получается немного более сложным, и требует вспомогательной булевой переменной: bool started = false; object mutex = new object(); new Thread(() => { lock (mutex) { started = true; Monitor.Pulse(mutex); } // ... }).Start(); lock (mutex) { while (!started) Monitor.Wait(mutex); // блокировка будет отпущена на период ожидания } И наконец, если не только основному потоку нужно дождаться порождённый поток, но и наоборот, порождённый поток должен задержаться до тех пор, пока основной поток не узнает, что он стартовал, у нас возникает так называемая задача рандеву: синхронизация одной точки выполнения у нескольких потоков. Это проще всего делать при помощи Barrier: var barrier = new Barrier(participantCount: 2); new Thread(() => { barrier.SignalAndWait(); // (*) // ... }).Start(); barrier.SignalAndWait(); // (*) Строки, отмеченные звёздочкой, будут ждать друг друга: первый из пришедших в эту строку потоков затормозится до прихода второго.
Комментариев нет:
Отправить комментарий