Блокировка (Монитор) внутренней реализации в .NET - PullRequest
33 голосов
/ 25 февраля 2011

Чтобы овладеть какой-то технологией, нужно знать, как это делается на уровне ниже абстракции.В случае многопоточного программирования будет полезно узнать о примитивах синхронизации.
Вот вопрос, как реализован Lock (Monitor) в .NET?

Меня интересуют такие моменты:
- использует ли она объекты ОС?;
- требует ли он пользовательский режим или режим ядра?;
- что такое издержки для потоков, которыев ожидании блокировки?;
- в каких случаях очередь потоков, ожидающая блокировки, может быть нарушена?.

Обновлено:
"Если блокировка блокируется несколькими потокамиони помещаются в очередь в «готовую очередь» и получают блокировку «первым пришел - первым обслужен». Примечание: нюансы в поведении Windows и CLR означают, что справедливость очереди иногда может нарушаться."[C # 4.0 в двух словах, Джозеф Албахари] Так вот о чем я спрашиваю в последнем вопросе о" нарушенной очереди ".

Ответы [ 2 ]

19 голосов
/ 25 февраля 2011

В статье Википедии есть довольно хорошее описание того, что такое "Монитор", а также лежащая в его основе технология, Условная переменная.

Обратите внимание, что .NET Monitor является правильной реализацией условной переменной; большинство опубликованных реализаций CV в Win32 неверны, даже те, которые можно найти в обычно авторитетных источниках, таких как Dr. Dobbs. Это потому, что CV не может быть легко построен из существующих примитивов синхронизации Win32 .

Вместо того, чтобы просто создавать поверхностную (и неправильную) оболочку над примитивами Win32, реализация .NET CV использует тот факт, что она работает на платформе .NET, реализует собственные очереди ожидания и т. Д.

18 голосов
/ 28 февраля 2011

После некоторых исследований я узнал ответы на свои вопросы.В целом CodeInChaos и Хенк Холтерман были правы, но вот некоторые детали.

Когда поток начинает бороться за блокировку с другими потоками, он сначала выполняет цикл ожидания ожидания, пытаясь получить блокировку.Все эти действия выполняются в пользовательском режиме .Затем, если не удалось создать объект ядра ОС Event, поток переключается в режим kernel-mode и ожидает сигнала от этого Event.

Так что ответьте на мои вопросы:
1. В лучшем случае нет, но в худшем да (Event объект лениво создает, если требуется);
2. В общем, он работает врежим, но если потоки конкурируют за блокировку слишком долго, поток может быть переключен в режим ядра (через вызов неуправляемой функции Win API);
3. Затраты на переключение из режима пользователя в режим ядра (~ 1000 циклов ЦП);
4. Microsoft заявляет, что это «честный» алгоритм, такой как FIFO, но это не гарантирует этого.(Например, если поток из «очереди ожидания» будет приостановлен, он перемещается в конец очереди, когда он будет возобновлен.)

...