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

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

39 ответов

Они НЕ одно и то же. Они используются для разных целей!
Хотя оба типа семафоров имеют полное / пустое состояние и используют один и тот же API, их использование сильно различается.

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

Семафор Mutex "принадлежит" той задаче, которая его выполняет. Если Задача B попытается передать мьютекс, который в настоящее время находится в Задаче A, вызов Задачи B возвратит ошибку и потерпит неудачу.

Мьютексы всегда используют следующую последовательность:

  - SemTake
  - Критический раздел
  - SemGive

Вот простой пример:

  Нить A Нить B
   Возьми Мутекс
     доступ к данным... возьми мьютекс <== заблокируешь...
   Предоставить Mutex доступ к данным <== Разблокирует...
                                Дайте мьютекс

Бинарный семафор
Бинарный семафор решает совершенно другой вопрос:

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

   Task A                      Task B
   ...                         Take BinSemaphore   <== wait for something
   Do Something Noteworthy
   Give BinSemaphore           do something    <== unblocks

Обратите внимание, что с двоичным семафором, B может взять семафор и A дать его.
Опять же, двоичный семафор НЕ защищает ресурс от доступа. Акт "Давать и брать семафор" в корне не связан.
Как правило, для одной и той же задачи не имеет смысла давать один и тот же двоичный семафор.

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

В Windows двоичные семафоры больше похожи на объекты событий, чем на мьютексы.

Пример туалета - приятная аналогия:

мьютекс:

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

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

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

Семафор:

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

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

Хорошие статьи на эту тему:

Из части 2:

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

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

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

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

Источник: http://www.geeksforgeeks.org/mutex-vs-semaphore/

Их семантика синхронизации очень различна:

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

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

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

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

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

Типичная реализация мьютекса имеет процесс или поток, выполняющий инструкцию test-and-set и оценивающий, установил ли мьютекс что-либо еще. Ключевым моментом здесь является то, что нет взаимодействия с планировщиком, поэтому мы понятия не имеем (и не волнует), кто установил блокировку. Затем мы либо оставляем наш временной интервал и пытаемся сделать это снова, когда задача перенесена, либо выполняем спин-блокировку. Спин-блокировка - это алгоритм вроде:

Count down from 5000:
     i. Execute the test-and-set instruction
    ii. If the mutex is clear, we have acquired it in the previous instruction 
        so we can exit the loop
   iii. When we get to zero, give up our time slice.

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

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

Основной алгоритм семафора выглядит так:

(somewhere in the program startup)
Initialise the semaphore to its start-up value.

Acquiring a semaphore
   i. (synchronised) Attempt to decrement the semaphore value
  ii. If the value would be less than zero, put the task on the tail of the list of tasks waiting on the semaphore and give up the time slice.

Posting a semaphore
   i. (synchronised) Increment the semaphore value
  ii. If the value is greater or equal to the amount requested in the post at the front of the queue, take that task off the queue and make it runnable.  
 iii. Repeat (ii) for all tasks until the posted value is exhausted or there are no more tasks waiting.

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

РЕДАКТИРОВАТЬ: Как справедливо заметил Эван, спин-блокировки будут тормозить однопроцессорный компьютер. Вы можете использовать спин-блокировку только на многопроцессорном блоке, потому что на одном процессоре процесс, удерживающий мьютекс, никогда не сбросит его, пока выполняется другая задача. Спин-блокировки полезны только на многопроцессорных архитектурах.

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

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

  • Семафор может быть Mutex, но Mutex никогда не может быть семафором. Это просто означает, что двоичный семафор может быть использован
    как Mutex, но Mutex никогда не может демонстрировать функциональность семафора.

  • И семафоры, и Mutex (по крайней мере, в последних версиях ядра) нерекурсивны по своей природе.
  • Никто не владеет семафорами, тогда как Mutex является собственностью, и владелец несет ответственность за них. Это важное отличие от точки зрения отладки.
  • В случае Mutex, поток, которому принадлежит Mutex, ответственен за его освобождение. Однако в случае семафоров это условие не требуется. Любой другой поток может подать сигнал на освобождение семафора с помощью smps (function.e_ot)

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

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

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

Mutex: Предположим, что у нас есть критический раздел, который T1 хочет получить к нему доступ, затем он выполняет следующие шаги. T1:

  1. Замок
  2. Используйте критический раздел
  3. отпереть

Двоичный семафор: работает на основе сигнала ожидания и сигнала. wait(s) уменьшает значение "s" на единицу, обычно значение "s" инициализируется значением "1", сигнал (ы) увеличивает значение "s" на единицу. если значение "s" равно 1, значит, никто не использует критическую секцию, когда значение равно 0, означает, что критическая секция используется. Предположим, что поток T2 использует критическую секцию, затем следует следующие шаги. T2:

  1. wait (s) // изначально значение s равно единице после вызова wait, его значение уменьшилось на единицу, т.е. 0
  2. Использовать критический раздел
  3. signal(s) // теперь значение s увеличивается и становится 1

Основное различие между Mutex и двоичным семафором заключается в Mutext, если поток блокирует критическую секцию, тогда он должен разблокировать критическую секцию, никакой другой поток не может разблокировать его, но в случае двоичного семафора, если один поток блокирует критическую секцию, используя функцию wait (s), тогда значение из s становятся "0", и никто не может получить к нему доступ, пока значение "s" не станет 1, но предположим, что какой-то другой поток вызывает сигнал (ы), а затем значение "s" становится 1, и это позволяет другой функции использовать критическую секцию. следовательно, в двоичном семафорном потоке нет владения.

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

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

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

Миф:

Пара статей говорит, что "двоичный семафор и мьютекс одинаковы" или "семафор со значением 1 является мьютексом", но основное отличие заключается в том, что Mutex может быть освобожден только тем потоком, который его получил, в то время как вы можете сигнализировать семафор из любого другого потока

Ключевые моменты:

• Поток может получить более одной блокировки (Mutex).

• Мьютекс может быть заблокирован более одного раза, только если это рекурсивный мьютекс, здесь блокировка и разблокировка для мьютекса должны быть одинаковыми

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

• Двоичный семафор и мьютекс похожи, но не одинаковы.

• Mutex является дорогостоящей операцией из-за протоколов защиты, связанных с ним.

• Основная цель мьютекса - добиться атомарного доступа или блокировки ресурса.

Mutex используются для "Механизмов блокировки". один процесс за раз может использовать общий ресурс

в то время как

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

Вы, очевидно, используете мьютекс для блокировки данных в одном потоке, к которым одновременно обращается другой поток. Предположим, что вы только что позвонили lock() и в процессе доступа к данным. Это означает, что вы не ожидаете, что какой-либо другой поток (или другой экземпляр того же кода потока) получит доступ к тем же данным, заблокированным тем же мьютексом. То есть, если один и тот же код потока выполняется в другом экземпляре потока, он блокируется, тогда lock() должен блокировать поток управления там. Это относится к потоку, который использует другой код потока, который также обращается к тем же данным и который также заблокирован тем же мьютексом. В этом случае вы все еще находитесь в процессе доступа к данным, и вам может потребоваться, скажем, еще 15 секунд, чтобы достичь разблокировки мьютекса (чтобы другой поток, блокируемый блокировкой мьютекса, разблокировался и позволил элементу управления доступ к данным). Разрешаете ли вы любой ценой позволить еще одному потоку просто разблокировать тот же мьютекс и, в свою очередь, разрешить потоку, который уже ожидает (блокирует) блокировку мьютекса, разблокировать и получить доступ к данным? Надеюсь, вы поняли, что я здесь говорю? Согласно согласованному универсальному определению!

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

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

Mutex контролирует доступ к одному общему ресурсу. Он предоставляет операции для получения () доступа к этому ресурсу и освобождения () его по завершении.

Семафор контролирует доступ к общему пулу ресурсов. Он предоставляет операции Wait() до тех пор, пока один из ресурсов в пуле не станет доступным, и Signal(), когда он возвращается в пул.

Когда количество ресурсов, которые защищает семафор, больше 1, оно называется счетным семафором. Когда он управляет одним ресурсом, он называется булевым семафором. Булев семафор эквивалентен мьютексу.

Thus a Semaphore is a higher level abstraction than Mutex. A Mutex can be implemented using a Semaphore but not the other way around.

Измененный вопрос - в чем разница между мьютексом и "двоичным" семафором в "Linux"?

Ответ: Ниже приведены различия: i) Область действия. Область действия мьютекса находится в адресном пространстве процесса, которое его создало, и используется для синхронизации потоков. Принимая во внимание, что семафор может использоваться в пространстве процессов и, следовательно, он может использоваться для межпроцессной синхронизации.

II) Mutex легкий и быстрее, чем семафор. Futex еще быстрее

iii) Mutex может быть успешно получен одним и тем же потоком несколько раз при условии, что он должен освобождать его одинаковое количество раз. Другой поток, пытающийся получить, заблокирует. Принимая во внимание, что в случае семафора, если тот же процесс пытается получить его снова, он блокируется, поскольку его можно получить только один раз.

Разница между двоичным семафором и мьютексом: ВЛАДЕНИЕ: Семафоры могут сигнализироваться (публиковаться) даже от не текущего владельца. Это означает, что вы можете просто отправлять сообщения из любой другой ветки, хотя вы не являетесь владельцем

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

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

http://www.geeksforgeeks.org/archives/9102 обсуждает в деталях.

Mutex механизм блокировки, используемый для синхронизации доступа к ресурсуSemaphore является сигнальным механизмом.

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

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

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

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

Мьютекс используется исключительно для взаимного исключения. Как взаимное исключение, так и синхронизация могут быть использованы двоичным кодом. Задача, которая взяла мьютекс, может дать только мьютекс. От ISR мьютекс не может быть дан. Возможно рекурсивное взятие семафоров взаимного исключения. Это означает, что задача, выполняемая до окончательного освобождения семафора, может взять семафор более одного раза. Mutex предоставляет опции для создания задачи, которая принимает значение DELETE_SAFE, что означает, что удаление задачи невозможно при удерживании мьютекса.

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

  • Случайный выпуск
  • Рекурсивный тупик
  • Задача Смертельный тупик

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

Например, вы можете включить атрибут проверки ошибок в вашем мьютексе. Ошибка проверки возврата мьютексов EDEADLK если вы попытаетесь заблокировать один и тот же дважды и EPERM если ты разблокируешь мьютекс, который не твой.

pthread_mutex_t mutex;
pthread_mutexattr_t attr;
pthread_mutexattr_init (&attr);
pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_ERRORCHECK_NP);
pthread_mutex_init (&mutex, &attr);

После инициализации мы можем поместить эти проверки в наш код следующим образом:

if(pthread_mutex_unlock(&mutex)==EPERM)
 printf("Unlock failed:Mutex not owned by this thread\n");

Лучшее решение

Единственная разница

1. Мьютекс -> блокировка и разблокировка принадлежат потоку, который блокирует мьютекс.

2.Semaphore -> Нет собственности т.е. если один поток вызывает semwait(s), любой другой поток может вызвать sempost(s) для снятия блокировки.

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

Когда мы пытаемся дать семафор, не беря его, он проходит. Но когда вы пытаетесь дать мьютекс, не беря его, это не получается. Я проверил это на платформе Windows. Включите USE_MUTEX для запуска того же кода, используя MUTEX.

#include <stdio.h>
#include <windows.h>
#define xUSE_MUTEX 1
#define MAX_SEM_COUNT 1

DWORD WINAPI Thread_no_1( LPVOID lpParam );
DWORD WINAPI Thread_no_2( LPVOID lpParam );

HANDLE Handle_Of_Thread_1 = 0;
HANDLE Handle_Of_Thread_2 = 0;
int Data_Of_Thread_1 = 1;
int Data_Of_Thread_2 = 2;
HANDLE ghMutex = NULL;
HANDLE ghSemaphore = NULL;


int main(void)
{

#ifdef USE_MUTEX
    ghMutex = CreateMutex( NULL, FALSE, NULL);
    if (ghMutex  == NULL) 
    {
        printf("CreateMutex error: %d\n", GetLastError());
        return 1;
    }
#else
    // Create a semaphore with initial and max counts of MAX_SEM_COUNT
    ghSemaphore = CreateSemaphore(NULL,MAX_SEM_COUNT,MAX_SEM_COUNT,NULL);
    if (ghSemaphore == NULL) 
    {
        printf("CreateSemaphore error: %d\n", GetLastError());
        return 1;
    }
#endif
    // Create thread 1.
    Handle_Of_Thread_1 = CreateThread( NULL, 0,Thread_no_1, &Data_Of_Thread_1, 0, NULL);  
    if ( Handle_Of_Thread_1 == NULL)
    {
        printf("Create first thread problem \n");
        return 1;
    }

    /* sleep for 5 seconds **/
    Sleep(5 * 1000);

    /*Create thread 2 */
    Handle_Of_Thread_2 = CreateThread( NULL, 0,Thread_no_2, &Data_Of_Thread_2, 0, NULL);  
    if ( Handle_Of_Thread_2 == NULL)
    {
        printf("Create second thread problem \n");
        return 1;
    }

    // Sleep for 20 seconds
    Sleep(20 * 1000);

    printf("Out of the program \n");
    return 0;
}


int my_critical_section_code(HANDLE thread_handle)
{

#ifdef USE_MUTEX
    if(thread_handle == Handle_Of_Thread_1)
    {
        /* get the lock */
        WaitForSingleObject(ghMutex, INFINITE);
        printf("Thread 1 holding the mutex \n");
    }
#else
    /* get the semaphore */
    if(thread_handle == Handle_Of_Thread_1)
    {
        WaitForSingleObject(ghSemaphore, INFINITE);
        printf("Thread 1 holding semaphore \n");
    }
#endif

    if(thread_handle == Handle_Of_Thread_1)
    {
        /* sleep for 10 seconds */
        Sleep(10 * 1000);
#ifdef USE_MUTEX
        printf("Thread 1 about to release mutex \n");
#else
        printf("Thread 1 about to release semaphore \n");
#endif
    }
    else
    {
        /* sleep for 3 secconds */
        Sleep(3 * 1000);
    }

#ifdef USE_MUTEX
    /* release the lock*/
    if(!ReleaseMutex(ghMutex))
    {
        printf("Release Mutex error in thread %d: error # %d\n", (thread_handle == Handle_Of_Thread_1 ? 1:2),GetLastError());
    }
#else
    if (!ReleaseSemaphore(ghSemaphore,1,NULL) )      
    {
        printf("ReleaseSemaphore error in thread %d: error # %d\n",(thread_handle == Handle_Of_Thread_1 ? 1:2), GetLastError());
    }
#endif

    return 0;
}

DWORD WINAPI Thread_no_1( LPVOID lpParam ) 
{ 
    my_critical_section_code(Handle_Of_Thread_1);
    return 0;
}


DWORD WINAPI Thread_no_2( LPVOID lpParam ) 
{
    my_critical_section_code(Handle_Of_Thread_2);
    return 0;
}

Мьютекс

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

Семафор

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

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

Я думаю, что большинство ответов здесь сбивали с толку, особенно те, которые говорили, что мьютекс может быть освобожден только процессом, который его держит, но семафор может сигнализировать о процессе. Вышеупомянутая строка довольно расплывчата с точки зрения семафора. Чтобы понять, мы должны знать, что существует два вида семафоров: один называется счетным семафором, а другой - двоичным семафором. При подсчете семафор обрабатывает доступ к количеству ресурсов n, где n может быть определено перед использованием. У каждого семафора есть переменная count, в которой хранится счетчик количества используемых ресурсов. Первоначально он установлен на n. Каждый процесс, который хочет использовать ресурс, выполняет операцию wait() над семафором (тем самым уменьшая счетчик). Когда процесс освобождает ресурс, он выполняет операцию release() (увеличивая счетчик). Когда счет становится 0,все ресурсы используются. После этого процесс ожидает, пока счетчик не станет больше 0. Теперь вот уловка: только процесс, удерживающий ресурс, может увеличить счет, никакой другой процесс не может увеличить счет, только процессы, удерживающие ресурс, могут увеличить счет, а процесс ожидание семафора снова проверяет, и когда он видит доступный ресурс, он снова уменьшает счетчик. Таким образом, с точки зрения двоичного семафора, только процесс, содержащий семафор, может увеличивать счетчик, и счетчик остается нулевым, пока он не перестанет использовать семафор и не увеличит счетчик, а другой процесс не получит возможность доступа к семафору.Теперь вот загвоздка: только процесс, который содержит ресурс, может увеличить счет, никакой другой процесс не может увеличить счет, только процессы, удерживающие ресурс, могут увеличить счетчик, а процесс, ожидающий семафор, снова проверяет, и когда он видит доступный ресурс, он снова уменьшает счет. Таким образом, с точки зрения двоичного семафора, только процесс, содержащий семафор, может увеличивать счетчик, и счетчик остается нулевым, пока он не перестанет использовать семафор и не увеличит счетчик, а другой процесс не получит возможность доступа к семафору.Теперь вот загвоздка: только процесс, который содержит ресурс, может увеличить счет, никакой другой процесс не может увеличить счет, только процессы, удерживающие ресурс, могут увеличить счетчик, а процесс, ожидающий семафор, снова проверяет, и когда он видит доступный ресурс, он снова уменьшает счет. Таким образом, с точки зрения двоичного семафора, только процесс, содержащий семафор, может увеличивать счетчик, и счетчик остается нулевым, пока он не перестанет использовать семафор и не увеличит счетчик, а другой процесс не получит возможность доступа к семафору.и count остается равным нулю, пока он не перестанет использовать семафор и не увеличит счетчик, а другой процесс не получит шанс получить доступ к семафору.и count остается равным нулю, пока он не перестанет использовать семафор и не увеличит счетчик, а другой процесс не получит шанс получить доступ к семафору.

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

MUTEX

До недавнего времени единственной спящей блокировкой в ​​ядре был семафор. Большинство пользователей семафоров создают семафор со счетчиком, равным единице, и рассматривают их как блокировку взаимного исключения - спящую версию спин-блокировки. К сожалению, семафоры довольно общие и не накладывают никаких ограничений на использование. Это делает их полезными для управления монопольным доступом в неясных ситуациях, таких как сложные танцы между ядром и пользовательским пространством. Но это также означает, что более простую блокировку сделать сложнее, а отсутствие принудительных правил делает невозможным любую автоматическую отладку или принудительное применение ограничений. В поисках более простой блокировки спящего режима разработчики ядра ввели мьютекс. Да, как вы теперь привыкли, это запутанное название. Давайте уточнить. Термин "мьютекс" - это общее название для обозначения любой спящей блокировки, которая обеспечивает взаимное исключение,например семафор со счетчиком использования один. В последних ядрах Linux имя собственное "мьютекс" теперь также является особым типом блокировки спящего режима, который реализует взаимное исключение. То есть мьютекс - это мьютекс.

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

  1. Тот, кто заблокировал мьютекс, должен его разблокировать. То есть вы не можете заблокировать мьютекс в одном контексте, а затем разблокировать его в другом. Это означает, что мьютекс не подходит для более сложной синхронизации между ядром и пользовательским пространством. Однако в большинстве случаев блокировка и разблокировка выполняется в одном контексте.
  2. Рекурсивные блокировки и разблокировки недопустимы. То есть вы не можете рекурсивно получить один и тот же мьютекс, и вы не можете разблокировать разблокированный мьютекс.
  3. Процесс не может выйти, удерживая мьютекс.
  4. Мьютекс не может быть получен обработчиком прерывания или нижней половиной, даже с помощью mutex_trylock().
  5. Мьютексом можно управлять только через официальный API: он должен быть инициализирован с помощью методов, описанных в этом разделе, и не может быть скопирован, инициализирован вручную или повторно инициализирован.

[1] Разработка ядра Linux, третье издание Роберт Лав

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

При использовании семафора вы можете заставить поток ждать семафор (скажем, поток A), пока другой поток (скажем, поток B) не завершит какую-либо задачу, а затем установить семафор для потока A, чтобы остановить ожидание и продолжить свою задачу.

Другие вопросы по тегам