В чем разница между семафорами и мьютексами, предоставляемыми библиотекой pthread?
Мьютекс pthreads против семафора
Ответы (9)
семафоры имеют синхронизированный счетчик, а мьютексы просто двоичные (истина/ложь).
Семафор часто используется в качестве окончательного механизма ответа на вопрос, сколько элементов ресурса используется — например, объект, представляющий n рабочих потоков, может использовать семафор для подсчета количества доступных рабочих потоков.
Правда в том, что вы можете представить семафор с помощью INT, который синхронизируется мьютексом.
Я собираюсь поговорить о Mutex и Binary-Semaphore. Вы, очевидно, используете мьютекс, чтобы предотвратить одновременный доступ к данным в одном потоке из другого потока.
(Предположим, что вы только что вызвали lock() и находитесь в процессе доступа к данным. Это означает, что вы не ожидаете, что какой-либо другой поток (или другой экземпляр того же кода потока) будет обращаться к тем же данным, заблокированным тот же мьютекс, то есть, если один и тот же код потока, выполняемый в другом экземпляре потока, попадает в блокировку, тогда функция lock() должна блокировать поток управления.)
Это относится к потоку, который использует другой код потока, который также обращается к тем же данным и также заблокирован тем же мьютексом.
В этом случае вы все еще находитесь в процессе доступа к данным, и вам может потребоваться, скажем, еще 15 секунд, чтобы достичь разблокировки мьютекса (чтобы другой поток, заблокированный в мьютексе, разблокировался и позволил элементу управления получить доступ к данным).
Вы когда-нибудь позволяли другому потоку просто разблокировать тот же мьютекс и, в свою очередь, позволяли потоку, который уже ожидает (блокируется) в блокировке мьютекса, разблокировать и получить доступ к данным? (Надеюсь, вы поняли, о чем я здесь говорю.)
Согласно согласованному универсальному определению,
- с «мьютексом» этого не может произойти. Ни один другой поток не может разблокировать замок в вашем потоке.
- с «двоичным семафором» это может случиться. Любой другой поток может разблокировать замок в вашем потоке.
Итак, если вы очень внимательно относитесь к использованию двоичного семафора вместо мьютекса, то вам следует быть очень осторожным в «объеме» блокировок и разблокировок, я имею в виду, что каждый поток управления, который попадает в каждую блокировку, должен вызывать вызов разблокировки, а также не должно быть «первой разблокировки», а всегда должна быть «первая блокировка».
Пример с туалетом
Мьютекс:
Является ключом от туалета. Один человек может иметь ключ - занять туалет - в то время. Закончив, человек передает (освобождает) ключ следующему человеку в очереди.
«Мьютексы обычно используются для сериализации доступа к разделу кода с повторным входом, который не может выполняться одновременно более чем одним потоком. Объект мьютекса позволяет только одному потоку войти в контролируемый раздел, заставляя другие потоки, которые пытаются получить доступ к этому разделу. ждать, пока первый поток не выйдет из этого раздела».
(Мьютекс на самом деле является семафором со значением 1.)
Семафор:
Это количество бесплатных одинаковых ключей от туалета. Например, скажем, у нас есть четыре туалета с одинаковыми замками и ключами. Счетчик семафоров - количество ключей - в начале устанавливается равным 4 (все четыре туалета свободны), затем значение счетчика уменьшается по мере прихода людей. Если все туалеты заполнены, т.е. свободных ключей не осталось, счетчик семафоров равен 0. Теперь, когда экв. один человек выходит из туалета, семафор увеличивается до 1 (один свободный ключ) и передается следующему человеку в очереди.
«Семафор ограничивает количество одновременных пользователей общего ресурса до максимального числа. Потоки могут запрашивать доступ к ресурсу (уменьшая значение семафора) и могут сигнализировать о том, что они закончили использование ресурса (увеличивая значение семафора)».
мьютекс используется, чтобы избежать состояния гонки между несколькими потоками.
тогда как семафор используется как синхронизирующий элемент, используемый в нескольких процессах.
мьютекс не может быть заменен двоичным семафором, поскольку один процесс ожидает семафор, а другой процесс освобождает семафор. В случае мьютекса и получение, и освобождение обрабатываются одним и тем же.
Разница между semaphore
и mutex
— это разница между механизмом и шаблоном. Разница заключается в их назначении (намерение) и в том, как они работают (поведенческие).
mutex
, barrier
, pipeline
– это шаблоны параллельного программирования. Mutex
используется (предназначено) для защиты critical section
и обеспечения mutual exclusion
. Barrier
заставляет агентов (поток/процесс) ждать друг друга.
Одной из особенностей (поведения) шаблона mutex
является то, что только разрешенные агенты (процессы или потоки) могут войти в критическую секцию, и только эти агенты могут добровольно выйти из нее.
Бывают случаи, когда mutex
позволяет работать только одному агенту. Есть случаи, когда он разрешает несколько агентов (несколько читателей) и запрещает некоторые другие агенты (писатели).
semaphore
— это механизм, который можно использовать (предназначено) для реализации различных шаблонов. Обычно это (поведение) флаг (возможно, защищенный взаимным исключением). (Один интересный факт заключается в том, что даже шаблон mutex
можно использовать для реализации семафора).
В популярной культуре semaphores
— это механизмы, предоставляемые ядрами, а mutexes
— библиотеки пользовательского пространства.
Обратите внимание, что существуют неправильные представления о semaphores
и mutexes
. Там написано, что semaphores
используются для synchronization
. А у mutexes
есть ownership
. Это связано с популярными книгами по ОС. Но правда, все мьютексы, семафоры и барьеры используются для синхронизации. Назначение мьютекса не ownership
, а mutual exclusion
. Это заблуждение привело к появлению популярного вопроса на собеседовании о разнице между mutexes
и binary-semaphores
.
Резюме,
intent- мьютекс, взаимное исключение
- семафор, реализовать шаблоны параллельного проектирования
- мьютекс, только разрешенный агент (агенты) входит в критическую секцию и только он (они) может выйти
- семафор, введите, если флаг говорит идти, в противном случае подождите, пока кто-нибудь не изменит флаг
С точки зрения дизайна mutex
больше похоже на state-pattern
, где алгоритм, выбранный состоянием, может изменить состояние. binary-semaphore
больше похоже на strategy-pattern
, где внешний алгоритм может изменить состояние и, в конечном итоге, алгоритм/стратегию, выбранную для выполнения.
Семафор больше используется как флаг, для которого вам действительно не нужно использовать RTOS/OS. Семафор может быть случайно или преднамеренно изменен другими потоками (скажем, из-за плохого кода). Когда вы используете мьютекс, он владеет ресурсами. Ни один другой поток не сможет получить к нему доступ, пока ресурс не освободится.
Мьютексы могут применяться только к потокам в одном процессе и не работают между процессами, как семафоры.
Мьютекс подобен семпафору с S=1.
Вы можете контролировать количество одновременных доступов с помощью семафора, но с мьютексом только один процесс может получить к нему доступ в каждый момент времени.
См. реализацию этих двух ниже: (все функции атомарны)
Семафор:
wait(S) {
while (S <= 0 )
; // busy wait
S--;
}
signal(S) {
S++;
}
Мьютекс:
acquire() {
while (!available)
; // busy wait
available = false;
}
release() {
available = true;
}
sem_t
в разделяемую память и использовать ее для синхронизации операций между процессами. С другой стороны, даже если вы не создаете несколько потоков, вы должны скомпилировать и связать с-pthread
, чтобы использоватьpthread_mutex_*
. (Некоторые платформы не применяют это, но это стандарт.) - person ephemient   schedule 14.01.2010man sem_init
в Linux говорит:Link with -pthread.
Итак, я думаю, что Linux не следует POSIX буквально. - person Alexis Wilke   schedule 28.05.2014