Мьютекс pthreads против семафора

В чем разница между семафорами и мьютексами, предоставляемыми библиотекой pthread?


person cppdev    schedule 14.01.2010    source источник
comment
Семафоры не предоставляются pthreads и могут использоваться и в непоточных программах.   -  person ephemient    schedule 14.01.2010
comment
любая конструкция синхронизации может использоваться в непоточном коде: P   -  person Hassan Syed    schedule 14.01.2010
comment
Отличие, которое я хотел подчеркнуть, заключается в том, что семафоры использовались до появления pthreads. Вы можете поместить sem_t в разделяемую память и использовать ее для синхронизации операций между процессами. С другой стороны, даже если вы не создаете несколько потоков, вы должны скомпилировать и связать с -pthread, чтобы использовать pthread_mutex_*. (Некоторые платформы не применяют это, но это стандарт.)   -  person ephemient    schedule 14.01.2010
comment
@ephemient, на самом деле man sem_init в Linux говорит: Link with -pthread. Итак, я думаю, что Linux не следует POSIX буквально.   -  person Alexis Wilke    schedule 28.05.2014


Ответы (9)


семафоры имеют синхронизированный счетчик, а мьютексы просто двоичные (истина/ложь).

Семафор часто используется в качестве окончательного механизма ответа на вопрос, сколько элементов ресурса используется — например, объект, представляющий n рабочих потоков, может использовать семафор для подсчета количества доступных рабочих потоков.

Правда в том, что вы можете представить семафор с помощью INT, который синхронизируется мьютексом.

person Hassan Syed    schedule 14.01.2010
comment
установка счетчика на 1 (любое значение, которое представляет) семафор становится мьютексом - person stacker; 14.01.2010
comment
Означает ли это, что мьютекс и бинарные семафоры — одно и то же? - person cppdev; 14.01.2010
comment
Одно существенное отличие (поскольку я видел, как люди совершают эту ошибку раньше): семафор может быть выделен и освобожден любым потоком в любой последовательности (при условии, что счетчик никогда не бывает отрицательным), а мьютекс может только быть разблокированным потоком, который его заблокировал. Попытка разблокировать мьютекс, который был заблокирован другим потоком, является поведением undefined. - person ephemient; 14.01.2010
comment
@ephemient, это был бы отличный ответ, очень проницательный - person Matt Joiner; 15.01.2010
comment
@ephemient: по указанной вами причине последнее утверждение в ответе ложно: вы НЕ МОЖЕТЕ представлять семафор с помощью INT, синхронизированного мьютексом, поскольку, если мьютекс удерживается, вы не можете увеличивать/уменьшать значение int из другого thread, и вам придется ждать, пока блокирующий поток освободит мьютекс. Основное отличие состоит в том, что мьютекс принадлежит, а семафор — нет. И это право собственности через принудительную синхронизацию передается INT. Таким образом, вы получаете некий гибрид принадлежащего семафора, что-то среднее между семафором без владельца и принадлежащим мьютексу. - person user1284631; 12.02.2013
comment
Я думаю, что в этом ответе по-прежнему отсутствует одно ОЧЕНЬ важное различие между семафором и мьютексом; это использование. Семафоры являются сигнальными механизмами в своей основе; тот факт, что они могут быть увеличены и уменьшены любым потоком, является просто результатом этого. Семафоры используются для передачи сигнала другим потокам управления о чем-то, связанном с синхронизацией (например, о заполнении/пустоте буфера). С другой стороны, мьютекс всегда используется для защиты множественного доступа к общему объекту. Это большая разница, и люди почему-то всегда ее упускают, или я никогда не понимаю, что они пытаются сказать. :П - person Fingolfin; 12.06.2013
comment
Я думаю, что большая разница между семафором и мьютексом заключается в том, что один из них - это механизм, а другой - шаблон проектирования. И мьютекс, и барьеры являются шаблонами параллельного программирования. Семафор — это механизм, который можно использовать для реализации различных шаблонов. - person shuva; 17.05.2016
comment
Проголосовали против. Правда в том, что вы можете представить семафор с помощью INT, который синхронизируется мьютексом, неверен. Если вы решите реализовать это таким образом, вам также понадобится условная переменная, чтобы отслеживать потоки, ожидающие семафора. - person Călin; 26.11.2020

Я собираюсь поговорить о Mutex и Binary-Semaphore. Вы, очевидно, используете мьютекс, чтобы предотвратить одновременный доступ к данным в одном потоке из другого потока.

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

Это относится к потоку, который использует другой код потока, который также обращается к тем же данным и также заблокирован тем же мьютексом.

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

Вы когда-нибудь позволяли другому потоку просто разблокировать тот же мьютекс и, в свою очередь, позволяли потоку, который уже ожидает (блокируется) в блокировке мьютекса, разблокировать и получить доступ к данным? (Надеюсь, вы поняли, о чем я здесь говорю.)

Согласно согласованному универсальному определению,

  • с «мьютексом» этого не может произойти. Ни один другой поток не может разблокировать замок в вашем потоке.
  • с «двоичным семафором» это может случиться. Любой другой поток может разблокировать замок в вашем потоке.

Итак, если вы очень внимательно относитесь к использованию двоичного семафора вместо мьютекса, то вам следует быть очень осторожным в «объеме» блокировок и разблокировок, я имею в виду, что каждый поток управления, который попадает в каждую блокировку, должен вызывать вызов разблокировки, а также не должно быть «первой разблокировки», а всегда должна быть «первая блокировка».

person Paxi    schedule 11.12.2012
comment
Мне нравится часть обзора. Это относится к части реализации, которая отличается двоичным семафором и мьютексом. - person shuva; 17.05.2016

Пример с туалетом

Мьютекс:

Является ключом от туалета. Один человек может иметь ключ - занять туалет - в то время. Закончив, человек передает (освобождает) ключ следующему человеку в очереди.

«Мьютексы обычно используются для сериализации доступа к разделу кода с повторным входом, который не может выполняться одновременно более чем одним потоком. Объект мьютекса позволяет только одному потоку войти в контролируемый раздел, заставляя другие потоки, которые пытаются получить доступ к этому разделу. ждать, пока первый поток не выйдет из этого раздела».

(Мьютекс на самом деле является семафором со значением 1.)

Семафор:

Это количество бесплатных одинаковых ключей от туалета. Например, скажем, у нас есть четыре туалета с одинаковыми замками и ключами. Счетчик семафоров - количество ключей - в начале устанавливается равным 4 (все четыре туалета свободны), затем значение счетчика уменьшается по мере прихода людей. Если все туалеты заполнены, т.е. свободных ключей не осталось, счетчик семафоров равен 0. Теперь, когда экв. один человек выходит из туалета, семафор увеличивается до 1 (один свободный ключ) и передается следующему человеку в очереди.

«Семафор ограничивает количество одновременных пользователей общего ресурса до максимального числа. Потоки могут запрашивать доступ к ресурсу (уменьшая значение семафора) и могут сигнализировать о том, что они закончили использование ресурса (увеличивая значение семафора)».

Источник

person Ankur    schedule 10.07.2016

мьютекс используется, чтобы избежать состояния гонки между несколькими потоками.

тогда как семафор используется как синхронизирующий элемент, используемый в нескольких процессах.

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

person C Learner    schedule 15.01.2010
comment
(-1) Неверное обобщение: во-первых, мьютексы могут быть общими для процессов, например: msdn.microsoft.com/en-us/library/ms682411(VS.85).aspx. Если в вашей системе нет именованных мьютексов, просто отобразите некоторую общую память и создайте свою собственную. - person Hassan Syed; 17.01.2010
comment
Нечестно помечать это как бесполезное. Я довольно много работал над M$. Легко сказать кому-то использовать общую память. в M$ все объекты ядра именованы и совместно используются. Мьютекс — это объект ядра. Мьютекс pthread — это CRITICAL_SECTION в M$. Невозможно разделить CRITICAL_SECTION между процессами! - person hackworks; 22.06.2010
comment
@hackworks — pthread_mutex можно инициализировать с флагом _POSIX_THREAD_PROCESS_SHARED, который позволяет ему работать в межпроцессном окружении: linux.die .net/man/3/pthread_mutexattr_init - person killdaclick; 02.12.2013

Разница между 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
  • мьютекс, взаимное исключение
  • семафор, реализовать шаблоны параллельного проектирования
behavior
  • мьютекс, только разрешенный агент (агенты) входит в критическую секцию и только он (они) может выйти
  • семафор, введите, если флаг говорит идти, в противном случае подождите, пока кто-нибудь не изменит флаг

С точки зрения дизайна mutex больше похоже на state-pattern, где алгоритм, выбранный состоянием, может изменить состояние. binary-semaphore больше похоже на strategy-pattern, где внешний алгоритм может изменить состояние и, в конечном итоге, алгоритм/стратегию, выбранную для выполнения.

person shuva    schedule 17.05.2016

В этих двух статьях подробно рассказывается о мьютексе и семафоры Также этот ответ на переполнение стека говорит аналогичный ответ.

person tsenapathy    schedule 04.11.2012

Семафор больше используется как флаг, для которого вам действительно не нужно использовать RTOS/OS. Семафор может быть случайно или преднамеренно изменен другими потоками (скажем, из-за плохого кода). Когда вы используете мьютекс, он владеет ресурсами. Ни один другой поток не сможет получить к нему доступ, пока ресурс не освободится.

person ajinkya    schedule 01.09.2015

Мьютексы могут применяться только к потокам в одном процессе и не работают между процессами, как семафоры.

person batteringRam    schedule 08.05.2011

Мьютекс подобен семпафору с S=1.

Вы можете контролировать количество одновременных доступов с помощью семафора, но с мьютексом только один процесс может получить к нему доступ в каждый момент времени.

См. реализацию этих двух ниже: (все функции атомарны)

Семафор:

wait(S) {
      while (S <= 0 )
         ; // busy wait
      S--;
}

signal(S) {
      S++;
}

Мьютекс:

acquire() {
      while (!available)
            ; // busy wait
      available = false;
}

release() {
      available = true;
}
person Ava    schedule 23.01.2020