Когда мы должны использовать мьютекс, а когда мы должны использовать семафор

Когда мы должны использовать мьютекс, а когда - семафор?


person Karthik Balaguru    schedule 28.10.2010    source источник
comment
возможный дубликат Что такое мьютекс и семафор в Яве? В чем главное отличие?   -  person Merlyn Morgan-Graham    schedule 28.10.2010


Ответы (12)


Вот как я запоминаю, когда что использовать -

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

Мьютекс: используйте мьютекс, когда вы (поток) хотите выполнить код, который не должен выполняться каким-либо другим потоком одновременно. Мьютекс «вниз» происходит в одном потоке, а «вверх» должен произойти в том же потоке позже. например: если вы удаляете узел из глобального связанного списка, вы не хотите, чтобы другой поток возился с указателями, пока вы удаляете узел. Когда вы получаете мьютекс и заняты удалением узла, если другой поток пытается получить тот же мьютекс, он будет переведен в спящий режим, пока вы не освободите мьютекс.

Spinlock: используйте спин-блокировку, когда вы действительно хотите использовать мьютекс, но вашему потоку не разрешено спать. например: обработчик прерывания в ядре ОС никогда не должен спать. Если это произойдет, система зависнет / выйдет из строя. Если вам нужно вставить узел в глобально общий связанный список из обработчика прерывания, получите спин-блокировку - вставьте узел - освободите спин-блокировку.

person Annu Gogatya    schedule 22.08.2012
comment
to add to: семафоры и мьютекс - это два способа обеспечить синхронизацию. семафор может быть больше связан с сигнализацией (например, сценарий проблемы производителя и потребителя), а мьютекс может быть больше связан с разрешением доступа к одному за раз (несколько запросов на доступ к общему ресурсу, но предоставляется только один за раз). [хорошая статья: geeksforgeeks.org/mutex-vs-semaphore/] - person parasrish; 24.04.2017

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

Его можно рассматривать как эквивалент обычного подсчетного семафора (со счетчиком, равным единице) и требования, чтобы он мог быть освобожден только тем же потоком, который его заблокировал (a).

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

Итак, если у вас есть несколько экземпляров ресурса (скажем, три ленточных накопителя), вы можете использовать семафор со счетчиком 3. Обратите внимание, что это не говорит вам, какой из этих ленточных накопителей у вас есть, просто то, что у вас есть определенное количество.

Также с помощью семафоров один шкафчик может заблокировать несколько экземпляров ресурса, например, для копирования с ленты на ленту. Если у вас есть один ресурс (скажем, область памяти, которую вы не хотите повреждать), более подходит мьютекс.

Эквивалентные операции:

Counting semaphore          Mutual exclusion semaphore
--------------------------  --------------------------
  Claim/decrease (P)                  Lock
  Release/increase (V)                Unlock

В сторону: если вы когда-нибудь задумывались над причудливыми буквами, используемыми для запроса и выпуска семафоров, то это потому, что изобретатель был голландцем. Probeer te verlagen означает пытаться уменьшить, в то время как verhogen означает увеличивать.


(a) ... или его можно рассматривать как нечто совершенно отличное от семафора, что может быть безопаснее, учитывая их почти всегда разные способы использования.

person paxdiablo    schedule 28.10.2010
comment
Хорошо, я тоже наткнулся на двоичный семафор. Когда нам нужно использовать двоичный семафор, а когда - мьютекс? - person Karthik Balaguru; 28.10.2010
comment
По сути, двоичный семафор является мьютексом и эквивалентен обычному семафору с единичным счетом. Могут быть различия в реализациях концепции, таких как эффективность или право собственности на ресурс (может быть выпущен кем-то, кроме заявителя, что я не согласен с BTW - ресурс должен быть только может быть выпущен тем потоком, в котором он был заявлен). - person paxdiablo; 28.10.2010
comment
Еще одно возможное отличие реализации - рекурсивный мьютекс. Поскольку существует только один ресурс, одному потоку может быть разрешено блокировать его несколько раз (при условии, что он также освобождает его столько раз). Это не так просто с ресурсом с несколькими экземплярами, поскольку вы можете не знать, хочет ли поток снова потребовать другой экземпляр или тот же экземпляр. - person paxdiablo; 28.10.2010
comment
Рекурсивные мьютексы - это зло, они показывают, что обработка ресурсов не освоена должным образом. - person Patrick Schlüter; 28.10.2010
comment
Они решают конкретную проблему. Тот факт, что проблема, которую они решают, - это люди, которые не вполне разбираются в мьютексах, никоим образом не должен умалять значение решения :-) - person paxdiablo; 28.10.2010
comment
Мьютекс полностью отличается от двоичного семафора. Извините, но это определение неверно - person Peer Stritzinger; 28.10.2010
comment
@PeerStritzinger Согласен, ваш ответ отражает различия в праве собственности между ними и причину, по которой мьютексы не используются в задачах синхронизации, а семафоры используются. Спасибо за статью и ответ. - person legends2k; 01.10.2013
comment
@ legends2k, это, вероятно, было лучшим комментарием к ответу Пера, а не моему. В любом случае, вопрос о праве собственности и другие различия рассматриваются в этом ответе, возможно, не так подробно, как у Peer, но, безусловно, есть. Вам также следует проголосовать за ответ Peer, если вы еще этого не сделали. - person paxdiablo; 01.10.2013
comment
@paxdiablo: Да, но мне это показалось немного неоднозначным; бинарный семафор комментария is делает его более подходящим. Да, я поддержал его ответ. - person legends2k; 01.10.2013
comment
@paxdiablo - хотя этот ответ можно считать технически правильным - действительно, он похож на описания, которые видели во многих других местах - я согласен с PeerStritzinger в том, что нецелесообразно приравнивать мьютекс к двоичному семафору. Это приводит к путанице в мыслях - как показывает ваш комментарий, ресурс может быть выпущен только тем потоком, который на него потребовал. Семафоры существуют так, что ответственность может быть передана кому-то другому - как жезл в гонке эстафетной палочки или передача жетона. Они не были бы полезны, если бы исходный поток участвовал в освобождении ресурса! - person ToolmakerSteve; 02.02.2017
comment
... A mutex - это заявление, которое не дает мне руки, пока я не закончу; для ресурса, о существовании которого уже известно. И это будет продолжаться после того, как мьютекс будет выпущен. binary semaphore подходит, когда ресурс не существует, пока producer не предоставит его. После того, как consumer приходит и получает этот ресурс он исчезает навсегда (если / пока producer не создаст другой ресурс). Это разные концепции. Да, мьютекс или семафор можно использовать не по назначению. Но это было бы ошибкой. - person ToolmakerSteve; 02.02.2017
comment
Хм. Даже в статье Wikipedia Semaphore обсуждается использование счетного семафора для управления пулом ресурсов. Но это сопряжено с серьезными рисками, см. Часть 1 Семафоры. К сожалению, я недостаточно эксперт, чтобы разрешить несоответствие между практикой и теорией. - person ToolmakerSteve; 02.02.2017
comment
@ToolmakerSteve, я не уверен, что вы поняли мои намерения. Я заявил, что мьютекс был подобен семафору со счетом один и ограничением, согласно которому запрашивающий поток должен быть высвобождающим. Я не утверждал, что у семафора есть такое ограничение. Попробую убрать ответ, чтобы лучше различать. - person paxdiablo; 02.02.2017

Очень важно понимать, что мьютекс не семафор со счетчиком 1!

По этой причине существуют такие вещи, как двоичные семафоры (которые на самом деле являются семафорами со счетом 1).

Разница между мьютексом и двоичным семафором заключается в принципе владения:

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

Предостережение: я написал «делает это возможным», если и как эти проблемы будут устранены, зависит от реализации ОС.

Поскольку мьютекс должен быть освобожден одной и той же задачей, это не очень хорошо для синхронизации задач. Но в сочетании с условными переменными вы получаете очень мощные строительные блоки для построения всех видов примитивов ipc.

Итак, моя рекомендация: если у вас есть чисто реализованные мьютексы и условные переменные (например, с потоками POSIX), используйте их.

Используйте семафоры только в том случае, если они точно соответствуют проблеме, которую вы пытаетесь решить, не пытайтесь создавать другие примитивы (например, rw-блокировки из семафоров, используйте для них мьютексы и условные переменные)

Есть много недопонимания мьютексов и семафоров. Лучшее объяснение, которое я нашел до сих пор, содержится в этой статье из трех частей:

Мьютекс против семафоров - Часть 1. Семафоры

Mutex vs. Семафоры - Часть 2: Мьютекс

Мьютекс против семафоров - Часть 3 (заключительная часть): Проблемы взаимного исключения

person Peer Stritzinger    schedule 28.10.2010
comment
URL-адреса этого сайта содержат забавные символы и поэтому не работают ... Я над этим работаю - person Peer Stritzinger; 28.10.2010
comment
Ссылки мертвы. Ответ не объясняет, в чем разница между спецификациями двоичного семафора и мьютекса. «Принцип владения» касается того, как используется примитив синхронизации, поэтому он не принадлежит спецификации. Голосование против. - person beroal; 11.03.2021

Хотя ответ @opaxdiablo совершенно правильный, я хотел бы отметить, что сценарий использования обоих вещей совершенно разный. Мьютекс используется для защиты частей кода от одновременного выполнения, семафоры используются для одного потока, чтобы сигнализировать о запуске другого потока.

/* Task 1 */
pthread_mutex_lock(mutex_thing);
    // Safely use shared resource
pthread_mutex_unlock(mutex_thing);



/* Task 2 */
pthread_mutex_lock(mutex_thing);
   // Safely use shared resource
pthread_mutex_unlock(mutex_thing); // unlock mutex

Сценарий семафора другой:

/* Task 1 - Producer */
sema_post(&sem);   // Send the signal

/* Task 2 - Consumer */
sema_wait(&sem);   // Wait for signal

Дополнительные пояснения см. На http://www.netrino.com/node/202.

person Patrick Schlüter    schedule 28.10.2010
comment
Ты прав. Даже если вы используете семафор с единичным счетчиком, вы подразумеваете что-то в том, что вы делаете, чем если бы вы использовали мьютекс. - person Omnifarious; 28.10.2010
comment
Я не уверен, что согласен с этим, хотя я не не согласен настолько сильно, что я буду отрицать вас :-) Вы говорите, что шаблон использования семафоров состоит в том, чтобы уведомлять потоки, но это именно то, что мьютексы работают, когда их ожидает другой поток, и именно то, что семафоры не делают, когда в sema_wait нет потоков :-) На мой взгляд, они оба относятся к ресурсам а уведомление, переданное другим потокам, является побочным эффектом (очень важным с точки зрения производительности) защиты. - person paxdiablo; 28.10.2010
comment
You say that the usage pattern of semaphores is to notify threads Одно замечание об уведомлении потоков. Вы можете безопасно вызвать sem_post из обработчика сигналов (pubs.opengroup.org/onlinepubs/ 009695399 / functions /), но не рекомендуется вызывать pthread_mutex_lock и pthread_mutex_unlock из обработчиков сигналов (manpages.ubuntu.com/manpages/lucid/man3/) - person ; 05.03.2013
comment
@paxdiablo: есть одно важное различие между этим двоичным семафором мьютекса - это поддержание счетчика ссылок. Мьютекс, или вы можете сказать, что любой условный мьютекс не поддерживает счетчик, связанный с блокировкой, в то время как семпахор используется для поддержания счетчика. Итак, sem_wait и sem_post поддерживают счет. - person Prak; 14.07.2013

См. «Пример туалета» - http://pheatt.emporia.edu/courses/2010/cs557f10/hand07/Mutex%20vs_%20Semaphore.htm:

Мьютекс:

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

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

(На самом деле мьютекс - это семафор со значением 1.)

Семафор:

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

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

person fornwall    schedule 28.10.2010

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

Ваш вопрос должен заключаться в том, в чем разница между мьютексом и семафором? А если быть более точным, следует задать вопрос: «Какая связь между мьютексом и семафором?»

(Я бы добавил этот вопрос, но я на сто процентов уверен, что какой-нибудь чрезмерно усердный модератор закроет его как дубликат, не понимая разницы между различием и отношением.)

В объектной терминологии мы можем заметить, что:

наблюдение.1 Семафор содержит мьютекс

наблюдение.2 Мьютекс не является семафором, а семафор не является мьютексом.

Есть некоторые семафоры, которые действуют как мьютекс, называемые двоичными семафорами, но они, черт возьми, НЕ мьютекс.

Существует специальный ингредиент, называемый Signaling (posix использует condition_variable для этого имени), необходимый для создания семафора из мьютекса. Думайте об этом как об источнике уведомлений. Если два или более потока подписаны на один и тот же источник уведомлений, то для пробуждения можно отправить им сообщение ОДНОМУ или ВСЕМ.

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

Вот где смятение вливается, как сезонный дождь.

Семафор со счетчиком, который может быть 0 или 1, НЕ является мьютексом.

Mutex имеет два состояния (0,1) и одно владение (задача). Семафор имеет мьютекс, несколько счетчиков и условную переменную.

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

  1. Одиночный счетчик со значением 0 или 1 и сигнализация, когда значение переходит в 1 И затем разблокирует одного из парней, ожидающих сигнала == Двоичный семафор

  2. Единый счетчик со значением от 0 до N и сигнализация, когда значение становится меньше N, и блокировка / ожидание, когда значение равно N == Семафор подсчета

  3. Единый счетчик со значением от 0 до N и сигнализация, когда значение переходит в N, и блокирует / ожидает, когда значения меньше N == Семафор барьера (ну, если они не вызывают его, тогда они должны.)

Теперь к вашему вопросу, когда что использовать. (ИЛИ довольно правильный вопрос версии 3, когда использовать мьютекс, а когда использовать двоичный семафор, поскольку нет сравнения с небинарным семафором.) Используйте мьютекс, когда 1. вам нужно настраиваемое поведение, которое не обеспечивается двоичным семафор, например, спин-блокировка, быстрая блокировка или рекурсивная блокировка. Обычно мьютексы можно настраивать с помощью атрибутов, но настройка семафора - это не что иное, как написание нового семафора. 2. вам нужен легкий ИЛИ более быстрый примитив

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

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

И, наконец, прочтите книгу, а не полагайтесь только на ТАК.

person Community    schedule 08.02.2013

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

Mutex = Это механизм блокировки владения, только поток, получивший блокировку, может снять блокировку.

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

person Saurabh Sengar    schedule 22.12.2014

Мьютекс предназначен для защиты общего ресурса.
Семафор предназначен для распределения потоков.

Mutex:
Представьте, что есть билеты на продажу. Мы можем смоделировать случай, когда многие люди покупают билеты одновременно: каждый человек является цепочкой для покупки билетов. Очевидно, нам нужно использовать мьютекс для защиты билетов, потому что это общий ресурс.


Семафор:
Представьте, что нам нужно произвести вычисление, как показано ниже:

c = a + b;

Кроме того, нам нужна функция geta() для вычисления a, функция getb() для вычисления b и функция getc() для вычисления c = a + b.

Очевидно, что мы не сможем выполнить c = a + b, если geta() и getb() не будут завершены.
Если три функции являются тремя потоками, нам нужно распределить три потока.

int a, b, c;
void geta()
{
    a = calculatea();
    semaphore_increase();
}

void getb()
{
    b = calculateb();
    semaphore_increase();
}

void getc()
{
    semaphore_decrease();
    semaphore_decrease();
    c = a + b;
}

t1 = thread_create(geta);
t2 = thread_create(getb);
t3 = thread_create(getc);
thread_join(t3);

С помощью семафора приведенный выше код может гарантировать, что t3 не будет выполнять свою работу, пока t1 и t2 не выполнят свою работу.

Одним словом, семафор должен заставить потоки выполняться в логическом порядке, тогда как мьютекс должен защищать совместно используемый ресурс.
Таким образом, это НЕ одно и то же, даже если некоторые люди всегда говорят, что мьютекс - это специальный семафор с начальным значением 1. Вы можете сказать и так, но обратите внимание, что они используются в разных случаях. Не заменяйте одно другим, даже если вы можете это сделать.

person Yves    schedule 14.12.2016
comment
Продажа билетов - отличный пример. Пример семафора немного неясен (по крайней мере, для меня). - person prayagupd; 16.08.2017
comment
Пример семафора @prayagupd - создание потоков в определенном порядке, тогда как продажа билетов не требует никакого порядка. Если есть три человека: a, b и c. Когда они приходят покупать билеты, нас совершенно не волнует порядок покупки билетов. Однако, если мы сделаем такой расчет: x = getx(); y = gety(); z = x + y; По какой-то причине мы используем три потока для выполнения трех задач, теперь порядок потоков очень важен, потому что мы не можем сделать x + y, пока getx и gety не завершены. Одним словом, семафор используется, когда мы заботимся о порядке выполнения многопоточности. - person Yves; 16.08.2017
comment
попался. Похоже на барьер. Я могу сказать, что дождитесь завершения потоков x и y, затем вычислите z = x + y. Я знаю, что в java есть CyclicBarrier. Кроме того, я не уверен, что могу сказать, что mapreduce также используется для семафоров, потому что я не могу reduce, пока не будут завершены все map. - person prayagupd; 16.08.2017
comment
@prayagupd Да. Вы можете так сказать. - person Yves; 16.08.2017

Как уже указывалось, семафор со счетчиком, равным единице, - это то же самое, что и «двоичный» семафор, который является тем же самым, что и мьютекс.

Основное, что я видел семафоры со счетчиком больше одного, - это ситуации производителя / потребителя, в которых у вас есть очередь определенного фиксированного размера.

Значит, у вас есть два семафора. Первый семафор изначально установлен как количество элементов в очереди, а второй семафор установлен на 0. Производитель выполняет операцию P над первым семафором, добавляет в очередь. и выполняет операцию V на втором. Потребитель выполняет операцию P со вторым семафором, удаляет его из очереди, а затем выполняет операцию V над первым.

Таким образом, производитель блокируется всякий раз, когда он заполняет очередь, а потребитель блокируется, когда очередь пуста.

person Omnifarious    schedule 28.10.2010

Все приведенные выше ответы хорошего качества, но этот - просто для запоминания. Название Мьютекс происходит от слова взаимоисключающий, поэтому у вас есть мотивация думайте о блокировке мьютекса как о взаимном исключении между двумя, как о только по одному за раз, и если я обладал им, вы можете получить его только после того, как я его отпущу. С другой стороны, такой случай не существует для Семафор похож на сигнал светофора (что также означает слово «семафор»).

person Nishant Sondhi    schedule 06.01.2018

Мьютекс - это особый случай семафора. Семафор позволяет нескольким потокам войти в критическую секцию. При создании семафора вы определяете, как могут быть разрешены потоки в критической секции. Конечно, ваш код должен уметь обрабатывать несколько обращений к этому критическому разделу.

person Frode Akselsen    schedule 27.11.2016

Бинарный семафор и мьютекс разные. С точки зрения ОС двоичный семафор и счетный семафор реализованы одинаково, и двоичный семафор может иметь значение 0 или 1.

Mutex -> Может использоваться только для одной-единственной цели взаимного исключения для критического участка кода.

Семафор -> Может использоваться для решения множества задач. Двоичный семафор может использоваться для сигнализации, а также для решения проблемы взаимного исключения. При инициализации 0 он решает проблему сигнализации, а при инициализации 1 решает проблему взаимного исключения.

Когда количество ресурсов больше и их необходимо синхронизировать, мы можем использовать семафор подсчета.

В своем блоге я подробно рассмотрел эти темы.

https://designpatterns-oo-cplusplus.blogspot.com/2015/07/synchronization-primitives-mutex-and.html

person Rags    schedule 27.05.2020