Что на самом деле делают мьютекс и семафор?
Я хочу получить разъяснения по поводу мьютекса и семафора.
Мой вопрос
- Что на самом деле делает мьютекс, когда поток пытается войти в область, заблокированную мьютексом, а. он ждет, когда будет снята блокировка? или б. он идет спать, пока замок не будет снят. В таком случае как снова проснуться при снятии блокировки?
- Тот же вопрос, что и 1, но в данном случае это семафор.
- Можете ли вы дать мне некоторый код относительно ожидания ожидания в pthread в C, а также случая, когда поток переходит в режим ожидания вместо ожидания? сон означает, что он заблокирован или сон - это еще один вид ожидания?
- Я хочу знать некоторые программы, в которых рассматриваются эти ситуации, например, некоторые исходные коды c, где реализовано ожидание, блокировка и т. д.
6 ответов
Когда поток пытается получить блокировку мьютекса, если этот мьютекс уже удерживается, обычно он использует вызов ядра ОС, чтобы указать, что он ожидает, а затем, когда поток, который в данный момент удерживает блокировку, разблокирует мьютекс, затем он вызовет ядро ОС, чтобы разбудить один из ожидающих потоков.
То же самое относится и к семафору, за исключением того, что оно блокируется только в том случае, если счетчик уменьшается ниже нуля, а потоки пробуждаются только при увеличении счетчика выше нуля.
Ожидание занята, когда вы не блокируетесь и не спите, ожидая чего-то, а постоянно проводите опрос в цикле, поэтому процессор всегда занят, но не делает ничего полезного.
Чтобы действительно достичь занятого ожидания, вам нужна атомарная переменная, но потоки POSIX не предоставляют такой возможности, поэтому вы не можете действительно написать занятое ожидание в pthreads. Самое близкое, что вы можете получить, это заблокировать мьютекс, прочитать флаг, разблокировать мьютекс, выполнить цикл, если флаг не был установлен. Это многократно блокирует и разблокирует мьютекс, но не ожидает готовности данных. В этой ситуации вы должны вместо этого использовать условную переменную.
Как правило, вы говорите, что поток спит, если он вызвал что-то вроде usleep
приостановить собственное исполнение на указанный период времени. Это в отличие от блокировки, когда он ожидает определенного сигнала, который будет предоставлен другим потоком.
Пожалуйста, посмотрите на: /questions/4125859/raznitsa-mezhdu-myuteksom-semaforom-i-spin-zamkami/4125871#4125871
Да, и мьютекс, и семафор синхронизируют объекты ядра, которые, когда поток пытается получить один из них, этот поток переводит в спящий режим, если этот объект уже принадлежит другому потоку.
Как вы уже догадались, этот спящий режим является критически важным, поскольку он позволяет другим потокам выполнять более полезную работу, чем просто "зацикливание / опрос".
Сон этих потоков заканчивается, когда поток, которому принадлежит объект, освобождает его.
Планировщик ОС не дает никакого среза выполнения спящим потокам.
Сравните это с блокировкой и спин-блокировкой, когда поток находится в состоянии "зацикливание / ожидание занято", тратя драгоценное время процессора, почти ничего не делая. Следовательно, в коде пользователя следует избегать блокировок. Вместо этого используйте критическую секцию, мьютекс или семафор!
Как видно из приведенной выше ссылки, оба объекта различны и должны использоваться в правильном контексте, который подходит лучше всего.
Думайте о мьютексе как о блокировке, которая позволяет владеть им только одному потоку. И что он имеет много безопасных атрибутов (владение, уведомление о прекращении, рекурсия и т. Д.).
И представьте себе семафор как блокировку, которая позволяет владеть им только определенному количеству потоков. Тем не менее, он не имеет много полезных атрибутов мьютекса.
Надеюсь это поможет.
- Что на самом деле делает мьютекс, когда поток пытается войти в область, заблокированную мьютексом, а. он ждет, когда будет снята блокировка? или б. он идет спать, пока замок не будет снят. В таком случае как снова проснуться при снятии блокировки?
Когда поток пытается получить блокировку мьютекса, он застревает и возвращается, только если блокировка предоставлена этому потоку. Блокировка распознается ОС, поэтому ОС знает, что пока такая блокировка не станет доступной для потока, ей больше нечего делать. Поток припаркован внутри ОС. Только ОС знает, что теперь у потока есть право собственности, и он возвращается в спящий режим. В системе с одним ЦП, в этом самом случае, если включен какой-то другой процесс, блокировка мьютекса вернется только тогда, когда у потока есть и то и другое - ЦП доступно, а также предоставлена блокировка!
Примечание: когда вы делаете fwrite
или же select
происходит то же самое. Поскольку ОС знает, что соответствующий ввод-вывод займет время, поток становится бездействующим. Когда данные поступают, поток становится работоспособным.
- Тот же вопрос, что и 1, но в данном случае это семафор. Можете ли вы дать мне некоторый код относительно ожидания ожидания в pthread в C, а также случая, когда поток переходит в режим ожидания вместо ожидания? сон означает, что он заблокирован или сон - это еще один вид ожидания?
В обоих случаях нет НИКАКОГО занятого ожидания. Если кто-то захочет подождать, чтобы убить время, пока вы не получите блокировку - вы фактически потерпели неудачу с целью блокировки! Подумайте об этом, скажем, у нас строго один процессор (и глупая ОС). Итак, что происходит, поток 1 пытается получить блокировку, так как блокировка лежит на потоке B, так что поток A начинает делать занятое ожидание. Следовательно, ЦП никогда не освобождается из потока А, а поток В никогда не получает возможности выполнить на ЦП - в конце оба потока оказываются в бесполезной ситуации. Блокировки ничего не делают с объектом потока. Но процесс блокировки всегда паркует потоки
Ожидание, сон, блокировка - все это означает одно и то же:
Поток выполняет системный вызов (получить мьютекс или семафор, подождать какое-то время, что угодно)
ОС берет на себя управление, запускает планировщик, помечает поток как ожидающий ресурс, обновляет состояние других потоков, а затем передает управление потоку, который готов к запуску. Если более одного потока готовы к запуску, один выбирается в соответствии с политикой планирования.
Как только ресурс становится доступным (посредством другого системного вызова, сделанного другим потоком), планировщик обновляет состояние предыдущего потока с момента ожидания ресурса до готовности к запуску, и поток получает контроль, как только политика планировщика примет решение так.
Пока поток ожидает ресурс, он не потребляет процессор. Со своей стороны опроса нет.
Это зависит от типа мьютекса (его поддерживающей реализации), некоторые заняты вращением с откатом, другие просто спят с объектом потока ядра, который затем будет просыпаться при обновлении мьютекса, а некоторые являются гибридом двух (В движке Valve Source используются гибридные). Его характеристики также зависят от того, когда и как часто ему нужно пересекать барьеры ядра / пользовательского пространства, поскольку иногда это может быть более затратным, чем просто вращаться немного дольше (посмотрите на это, если вы хотите получить больше от вращающейся и спящей сторон).
Мьютексы, как правило, предназначены для записи в один поток за раз (хотя они могут поддерживать рекурсивный вход в один и тот же поток). Семафоры, с другой стороны, допускают только n потоков одновременно, чтобы попытаться получить его (см. Эту запись MSDN или сравнительную запись Intel).
Спящий поток обычно означает, что он отказывается от своего временного интервала вычисления распределения до его готовности к пробуждению, а планировщик ОС дает ему еще один временной интервал. лучшие примеры, которые вы, вероятно, найдете, будут на самом деле в исходных текстах ядра Linux (или любой другой ОС с открытым исходным кодом).
Говоря простыми словами, Mutex предназначен для вещей, когда вас интересует 1 блокировка.... Семафор предназначен для нескольких блокировок... Я постараюсь выслать вам образцы. Я помню, что у меня были некоторые задания, связанные с семафором и мьютексом в C.. Что касается концепции, то здесь что-то смешное http://geekswithblogs.net/shahed/archive/2006/06/09/81268.aspx:)
Спасибо