Когда мы должны использовать мьютекс и когда мы должны использовать семафор - PullRequest
102 голосов
/ 28 октября 2010

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

Ответы [ 11 ]

82 голосов
/ 22 августа 2012

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

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

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

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

55 голосов
/ 28 октября 2010

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

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

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

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

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

Эквивалентными операциями являются:

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

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


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

45 голосов
/ 28 октября 2010

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

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

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

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

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

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

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

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

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

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

Мьютекс против семафоров. Часть 2. Мьютекс

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

13 голосов
/ 28 октября 2010

Хотя ответ @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_lock(mutex_thing);

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

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

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

См. http://www.netrino.com/node/202 для дальнейших объяснений

9 голосов
/ 28 октября 2010

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

Мьютекс:

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

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

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

Семафор:

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

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

7 голосов
/ 08 февраля 2013

Стараюсь не звучать глупо, но не могу с собой поделать.

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

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

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

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

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

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

Существует специальный ингредиент под названием Сигнализация (для этого имени 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. Вы хотите легкий или быстрый примитив

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

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

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

5 голосов
/ 22 декабря 2014

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

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

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

3 голосов
/ 14 декабря 2016

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

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. Вы тоже можете так сказать, но, пожалуйста,Они используются в разных случаях.Не заменяйте одно другим, даже если вы можете это сделать.

1 голос
/ 07 января 2018

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

1 голос
/ 27 ноября 2016

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

...