#c_sharp #многопоточность
Подскажите, как выполняется данный код: lock (locker) { while (x == 0) { if (y > 0) { Monitor.Pulse(locker); break; } Monitor.Wait(locker); } // что-то еще делаем } Задача - синхронизация потоков. Допустим есть очередь, в которую один поток пишет, другой из нее читает. Вот пока эта очередь пуста, поток "читатель" должен ждать пока не появятся данные. Я хочу понять для себя, что происходит при вызове Monitor.Wait и Monitor.Pulse. Т.е. когда очередь пуста, мы вызываем Monitor.Wait, поток переходит в режим ожидания, пока ресурс не освободиться (пока не будет данных для чтения), т.е. пока поток "писатель" не запишет данные и не предупредит следующий поток что ресурс скоро освободится командой Monitor.Pulse. Вопрос в следующем, когда поток выходит из состояния - Monitor.Wait, т.е. в цикле while (x == 0) x - изменится, будет ли еще раз проверяться условие if (y > 0) либо же будет исполняться следующий после цикла код?
Ответы
Ответ 1
Когда вы вызовите Wait, то ваш поток освободит блокирующий объект locker и заблокирует текущий поток. Цикл не завершится. Функция Wait в потоке1 завершится только тогда, кода другой поток(поток2) вызовет функцию Pulse(или PulseAll) для этого объекта и освободит блокирующий объект. Пока поток2 не освободит объект блокировки, функция Wait в потоке1 не завершится. Стоит отметить, что функции Wait, Pulse, PulseAll не могут быть вызваны, если текущий поток не является владельцем блокировки, поэтому обертка их в lock(locker) обязательна. В противном случае, при вызове этих методов возникнет исключение SynchronizationLockException. Ниже поясняющий пример работы функций public static void Main() { object locker = new object(); int x = 0; int y = 0; Task.Run(() => { Thread.Sleep(2000); lock (locker) { Console.WriteLine("Sending a signal..."); Monitor.Pulse(locker); Console.WriteLine("The signal was sent"); x = 1; Thread.Sleep(5000); Console.WriteLine("Sleep in lock finished"); } }); lock (locker) { while (x == 0) { if (y > 0) { Monitor.Pulse(locker); break; } Console.WriteLine("Wait..."); Monitor.Wait(locker); Console.WriteLine("Wait finished"); } Console.WriteLine("While finished"); } } Вывод программы будет следующий: Wait... Sending a signal... The signal was sent Sleep in lock finished Wait finished While finished Ответ на вопрос: Если Wait завершится, условие цикла при x !=0 будет false, соответственно цикл завершится и будет выполнятся код после цикла. Повторной проверки y>0 внутри цикла в этом случае невозможна!
Комментариев нет:
Отправить комментарий