Semaphore.WaitOne/Release vs Monitor.Pulse/Wait

Теперь мне кажется, что функционально Semaphore.WaitOne/Release равно Monitor.Wait/Pulse. Пропуск межпроцессорных возможностей, скорость (да, монитор управляется) другие нефункциональные различия, что такое реальная разница?

Ответ 1

Основной целью Semaphore является управление доступом к конечному набору ресурсов. Тема может участвовать в приобретении resouce, вызывая WaitOne и Release. Тед должен вызвать WaitOne для получения ресурса. Тем не менее, он будет блокироваться только в том случае, если счет семафора достигнет 0, иначе поток можно будет немедленно получить. Как только этот поток будет завершен, он должен вызвать Release, чтобы сигнализировать семафор, что дополнительный слот был освобожден для другого потока.

Monitor.Wait и Monitor.Pulse сильно различаются. В первую очередь не учитывается счет. Если Pulse вызывается в отсутствие какого-либо вызова Wait, тогда сигнал игнорируется и отбрасывается. Он не ставится в очередь так же, как семафор. На самом деле поведение Wait и Pulse вообще не имеет смысла. Wait просто ждет изменения состояния приобретенной блокировки (полученной из Monitor.Enter). Pulse - это сигнал, что что-то изменилось. Вот почему вы часто видите Wait, вызванный в цикле while. Ожидающий поток должен повторить условие ожидания, потому что он не знает, что изменилось!

Monitor.Wait и Monitor.Pulse являются фундаментальными механизмами синхронизации, которые могут использоваться для создания практически любого другого устройства синхронизации, включая семафоры.

Ответ 2

Monitor.Wait/Pulse предоставляет вам переменную условия, которая больше похожа на событие auto- reset, чем семафор (но не точно). Основное различие заключается в том, что семафор имеет счет, что означает, что вам не нужно ничего блокировать, чтобы вы не пропустили пульс (в отличие от Monitor.Wait).