Я сделал поддержку CLR классов & для нарезания резьбы в DotGNU и у меня есть несколько мыслей ...
Если вы не требуете перекрестной блокировки процесса вы всегда должны избегать использования мьютекса & семафоров. Эти классы в .NET являются обертками вокруг Mutex и Семафоров Win32 и имеют довольно большой вес (для них требуется контекстный переключатель в ядро, которое дорого - особенно, если ваша блокировка не находится под угрозой).
Как упоминалось выше, оператор блокировки C# является маской компилятора для Monitor.Enter и Monitor.Exit (существующий в попытке/наконец).
Мониторы имеют простой, но мощный механизм сигнала/ожидания, который не имеет Mutexes с помощью методов Monitor.Pulse/Monitor.Wait. Эквивалент Win32 будет объектами событий через CreateEvent, которые на самом деле также существуют в .NET как WaitHandles. Модель Pulse/Wait похожа на pthread_signal и pthread_wait от Unix, но быстрее, потому что они могут быть полностью пользовательскими режимами в непротиворечивом случае.
Monitor.Pulse/Wait прост в использовании. В одном потоке мы блокируем объект, проверяем флаг/состояние/свойство, и если это не то, что мы ожидаем, вызовите Monitor.Wait, который отпустит блокировку и дождитесь отправки импульса. Когда ожидание вернется, мы вернемся назад и снова проверим флаг/состояние/свойство. В другом потоке мы блокируем объект всякий раз, когда мы меняем свойство flag/state /, а затем вызываем PulseAll, чтобы разбудить любые прослушивающие потоки.
Часто мы хотим, чтобы наши классы были потокобезопасными, поэтому мы помещаем блокировки в наш код. Однако часто бывает, что наш класс будет использоваться только одним потоком. Это означает, что блокировки бесполезно замедляют наш код ... именно здесь умная оптимизация в среде CLR может повысить производительность.
Я не уверен в реализации блокировок Microsoft, но в DotGNU и Mono флаг состояния блокировки хранится в заголовке каждого объекта. Каждый объект в .NET (и Java) может стать блокировкой, поэтому каждый объект должен поддерживать это в своем заголовке. В реализации DotGNU существует флаг, который позволяет использовать глобальную хэш-таблицу для каждого объекта, который используется как блокировка, - это имеет преимущество устранения 4-байтных служебных данных для каждого объекта. Это не очень удобно для памяти (особенно для встроенных систем, которые не сильно загружены в потоки), но они поражают производительность.
Оба Mono и DotGNU эффективно использовать семафоры для выполнения блокировки/в режиме ожидания, но использовать стиль SpinLock compare-and-exchange операции, чтобы устранить необходимость фактически выполнить жесткие блокировки, если это действительно необходимо:
Вы можете увидеть пример того, как мониторы могут реализовать здесь:
http://cvs.savannah.gnu.org/viewvc/dotgnu-pnet/pnet/engine/lib_monitor.c?revision=1.7&view=markup
Эта ссылка помогло мне: http://www.albahari.com/threading/ – Raphael 2014-01-08 12:45:49