Реализация и сигнализация Mutex

Когда мьютекс уже заблокирован T1, а T2 пытается его заблокировать, каков процесс для T2?

Я думаю, что это происходит примерно так:

-T2 пытается блокировать, терпеть неудачу, может быть, спрятать бит, а затем набирает доход...
-T2 планируется выполнить несколько раз, пытается заблокировать сбои, дает...
-Eventually T1 разблокируется, T2 запланирован для выполнения и управляет блокировкой мьютекса...

Разблокирует ли T1 явное указание на планировщик или другие потоки, которые мьютекс разблокирован? Или он просто разблокируется и оставляет планировщику планировать заблокированные потоки, когда он считает это подходящим (например, у планировщика нет понятия заблокированных потоков и не относится к ним как к специальным)?

Ответ 1

Короче: да, возможно...

Это детали реализации, и довольно сложно сказать, по крайней мере, не зная, в какой операционной системе вы говорите. Как правило, разблокировка мьютекса будет отмечать только ожидаемый поток как "runnable", но не (обязательно) вызывает планировщик в это время - и даже если планировщик вызывается, это не означает, что T2 будет следующим потоком бежать.

В Linux код входит в mutex_unlock(), который проверяет, есть ли какая-либо ожидающая задача (проверяя, является ли счет блокировки меньше нуля - он начинается с 1 для разблокировки, один запрос блокировки получает его до нуля, дальнейшая попытка блокировки сделает его отрицательным). Если есть еще один процесс ожидания, он вызывает "медленную разблокировку пути", которая через пару функций перенаправления, чтобы разрешить детали реализации, заканчивается в __mutex_unlock_common_slowpath - несколько строк ниже, есть вызов wake_up_process, который в конечном итоге заканчивается try_to_wake_up - который по сути просто ставит задачу "готов к запуску", а затем вызывает планировщик (через несколько уровней функций!)

Ответ 2

Это зависит от вашей операционной системы. Я видел, как только вращался, вращаясь с переменными состояния yield, переменными общего назначения в ядре, контролируемым пользовательским планированием и специализированными фиксаторами с поддержкой ядра.

Спиннинг и вращение с yield имеют ужасную производительность. Теоретически контролируемое пользователем планирование (см. Активация планировщика) должно иметь лучшую производительность, но насколько я знаю, никто никогда не делал это правильно случаев. Переменные условия общего назначения в ядре и специальные блокирующие примитивы с поддержкой ядра должны выполнять более или менее то же самое с futex в Linux как лучший пример из последних.

Бывают ситуации, когда спиннинг может иметь лучшую производительность. В Solaris некоторый фиксирующий примитив в ядре имеет адаптивный режим, в котором блокировка вращается до тех пор, пока процесс, удерживающий блокировку, работает на другом процессоре. Если владелец замка спит или получает превенцию, официант замка тоже ложится спать. В других ядрах есть классы блокировок, в которых владелец замка не может быть выгружен или спящий, удерживая замок, поэтому в этих случаях вращение тоже хорошо работает. В целом, хотя, в частности, в области правдоподобия, спиннинг имеет такие ужасные дегенеративные случаи (процесс прядения вращается, пока он не освобождается, чтобы позволить владельцу замка работать), что это очень плохо для производительности. Обратите внимание, что специализированные блокирующие примитивы, такие как futex, могут реализовывать такие оптимизации, как обычно, переменные состояния общего назначения обычно не могут.

Ответ 3

Скажем, у нас есть следующий сценарий:

 1. T1 got M1. M1 locked.
 2. T2 tries to get M1 and gets blocked as M1 is locked.
 3. T3 tries to get M1 and gets blocked as M1 is locked.
 4. ...some time later...
 5. T1 unlocks M1.*
 6. T2 got M1.
 7. T3 is unblocked and tries to get M1 but is blocked again as T2 got M1 first.

* Системный вызов разблокировать должен уведомлять все заблокированные задачи/процессы/потоки, которые заблокированы при блокировке мьютекса вызов. Затем они выполняются запланировано. Это не означает, что они выполняются, поскольку в ходе выполнения может быть уже кто-то. Как утверждают другие, это зависит от реализации, как это делается. Если вы действительно хотите это хорошо изучить, я рекомендую эту книгу