Есть ли разница между двоичным семафором и мьютексом или они по сути одинаковы?
Есть ли разница между двоичным семафором и мьютексом или они по сути одинаковы?
Ответы:
Они НЕ одно и то же. Они используются для разных целей!
Хотя оба типа семафоров имеют полное / пустое состояние и используют один и тот же API, их использование сильно отличается.
Семафоры взаимного исключения Семафоры
взаимного исключения используются для защиты общих ресурсов (структура данных, файл и т. Д.).
Семафор Mutex «принадлежит» задаче, которая его выполняет. Если задача B попытается передать мьютекс, который в данный момент находится в задаче A, вызов задачи B вернет ошибку и произойдет сбой.
Мьютексы всегда используют следующую последовательность:
- SemTake - Критический раздел - SemGive
Вот простой пример:
Нить A Нить B Возьми Мутекс доступ к данным ... возьми мьютекс <== заблокируешь ... Предоставить Mutex доступ к данным <== Разблокирует ... Дайте мьютекс
Двоичный семафор
Двоичный семафор решает совершенно другой вопрос:
Task A Task B
... Take BinSemaphore <== wait for something
Do Something Noteworthy
Give BinSemaphore do something <== unblocks
Обратите внимание, что с двоичным семафором B может взять семафор и A дать его.
Опять же, двоичный семафор НЕ защищает ресурс от доступа. Акт «Давать и брать семафор» в корне не связан.
Как правило, для одной и той же задачи не имеет смысла давать один и тот же двоичный семафор.
поэтому семафоры больше подходят для некоторых проблем синхронизации, таких как производитель-потребитель.
В Windows двоичные семафоры больше похожи на объекты событий, чем на мьютексы.
Mutex can be released only by thread that had acquired it
- Я только что попробовал с простой программой, основанной на pthread_mutex, поток может разблокировать мьютекс, заблокированный в основном потоке
Пример туалета - приятная аналогия:
мьютекс:
Это ключ к туалету. Один человек может иметь ключ - занять туалет - в самый раз. Когда закончено, человек дает (освобождает) ключ следующему человеку в очереди.
Официально: «Мьютексы обычно используются для сериализации доступа к разделу повторно поступающего кода, который не может быть выполнен одновременно более чем одним потоком. Объект мьютекса допускает только один поток в контролируемый раздел, заставляя другие потоки, которые пытаются получить доступ к этот раздел, чтобы дождаться выхода первого потока из этого раздела. " Ссылка: библиотека разработчика Symbian
(Мьютекс - это действительно семафор со значением 1.)
Семафор:
Количество бесплатных идентичных ключей от туалета. Например, у нас есть четыре туалета с одинаковыми замками и ключами. Счетчик семафоров - количество ключей - вначале устанавливается равным 4 (все четыре туалета свободны), тогда значение счетчика уменьшается по мере прихода людей. Если все туалеты заполнены, т.е. свободных ключей не осталось, число семафоров равно 0. Теперь, когда уравнение один человек выходит из туалета, семафор увеличивается до 1 (один свободный ключ) и передается следующему человеку в очереди.
Официально: «Семафор ограничивает число одновременных пользователей общего ресурса до максимального числа. Потоки могут запрашивать доступ к ресурсу (уменьшая семафор), и могут сигнализировать, что они закончили использовать ресурс (увеличивая семафор). " Ссылка: библиотека разработчика Symbian
Хорошие статьи на эту тему:
Из части 2:
Мьютекс похож на принципы двоичного семафора с одним существенным отличием: принцип владения. Владение - это простая концепция, что когда задача блокирует (приобретает) мьютекс, только она может разблокировать (освободить) его. Если задача пытается разблокировать мьютекс, который она не заблокировала (и поэтому не владеет), возникает условие ошибки, и, самое главное, мьютекс не разблокируется. Если объект взаимного исключения не принадлежит, то, независимо от того, как он называется, он не является мьютексом.
Поскольку ни один из приведенных выше ответов не устраняет путаницу, вот тот, который устраняет мою путаницу.
Строго говоря, мьютекс - это механизм блокировки, используемый для синхронизации доступа к ресурсу. Только одна задача (может быть потоком или процессом, основанным на абстракции ОС) может получить мьютекс. Это означает, что с мьютексом будет владение, и только владелец может снять блокировку (мьютекс).
Семафор - это сигнальный механизм ( сигнал типа «Я готов, ты можешь продолжать»). Например, если вы слушаете песни (считаете, что это одно задание) на своем мобильном телефоне, и в то же время ваш друг звонил вам, будет запущено прерывание, при котором подпрограмма обработки прерываний (ISR) будет сигнализировать о пробуждении задачи обработки вызова. ,
Их семантика синхронизации очень различна:
Таким образом, можно видеть мьютекс как токен, передаваемый от задачи к задачам, а семафор - как красный светофор (он сигнализирует кому-то, что он может продолжить).
На теоретическом уровне они не отличаются семантически. Вы можете осуществить взаимную блокировку с помощью семафоров или наоборот (см здесь для примера). На практике реализация отличается, и они предлагают немного разные услуги.
Практическое отличие (с точки зрения окружающих их системных служб) состоит в том, что реализация мьютекса направлена на то, чтобы стать более легким механизмом синхронизации. В оракуле мьютексы известны как защелки, а семафоры - как ожидания .
На самом низком уровне они используют какой-то атомный тест и механизм установки . Это считывает текущее значение ячейки памяти, вычисляет некоторый тип условия и записывает значение в этом месте в одной инструкции, которая не может быть прервана . Это означает, что вы можете приобрести мьютекс и проверить, есть ли у кого-то еще до вас.
Типичная реализация мьютекса имеет процесс или поток, выполняющий инструкцию 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.
В случае двоичного семафора основное практическое различие между ними заключается в характере системных служб, окружающих фактическую структуру данных.
РЕДАКТИРОВАТЬ: Как справедливо указал Эван, спин-блокировки будут замедлять однопроцессорный компьютер. Вы можете использовать спин-блокировку только на многопроцессорном блоке, потому что на одном процессоре процесс, удерживающий мьютекс, никогда не сбросит его, пока выполняется другая задача. Спин-блокировки полезны только на многопроцессорных архитектурах.
futex
существует системный вызов Linux , чтобы помочь реализации мьютекса / семафора в пользовательском пространстве с низкой задержкой. en.wikipedia.org/wiki/Futex ) В быстром пути без конфликтов, или если ресурс скоро станет доступным, у вас никогда не будет лишних затрат системный вызов. Но вы не тратите больше нескольких микросекунд на ожидание (вращение). Конечно, настройка параметров отката и ожидания спин-цикла зависит от оборудования и рабочей нагрузки, но стандартная библиотека обычно имеет разумные варианты.
Хотя мьютекс и семафоры используются в качестве примитивов синхронизации, между ними существует большая разница. В случае мьютекса, только поток, который заблокировал или получил мьютекс, может разблокировать его. В случае семафора поток, ожидающий семафора, может сигнализироваться другим потоком. Некоторые операционные системы поддерживают использование мьютекса и семафоров между процессами. Обычно использование создается в общей памяти.
Мьютекс: Предположим, что у нас есть критическая секция, которую T1 хочет получить к ней доступ, затем она следует нижеуказанным шагам. T1:
Двоичный семафор: работает на основе сигналов ожидания и сигнала. wait (s) уменьшает значение "s" на единицу, обычно значение "s" инициализируется значением "1", сигнал (ы) увеличивает значение "s" на единицу. если значение "s" равно 1, значит, никто не использует критическую секцию, когда значение равно 0, означает, что критическая секция используется. Предположим, что поток T2 использует критическую секцию, затем следует следующие шаги. T2:
Основное различие между Mutex и двоичным семафором заключается в Mutext, если поток блокирует критическую секцию, тогда он должен разблокировать критическую секцию, никакой другой поток не может разблокировать его, но в случае двоичного семафора, если один поток блокирует критическую секцию, используя функцию wait (s), тогда значение из s становится "0", и никто не может получить к нему доступ, пока значение "s" не станет 1, но предположим, что какой-то другой поток вызывает сигнал (ы), а затем значение "s" становится 1, и это позволяет другой функции использовать критическую секцию. следовательно, в двоичном семафорном потоке нет владения.
В Windows есть два различия между мьютексами и двоичными семафорами:
Мьютекс может быть освобожден только тем потоком, у которого есть владелец, то есть потоком, который ранее вызывал функцию Wait (или который стал владельцем при создании). Семафор может быть освобожден любым потоком.
Поток может повторно вызывать функцию ожидания в мьютексе без блокировки. Однако, если вы дважды вызываете функцию ожидания для двоичного семафора без освобождения промежуточного семафора, поток блокируется.
Вы, очевидно, используете мьютекс для блокировки данных в одном потоке, к которым одновременно обращается другой поток. Предположим, что вы только что позвонилиlock()
и в процессе доступа к данным. Это означает, что вы не ожидаете, что какой-либо другой поток (или другой экземпляр того же кода потока) получит доступ к тем же данным, заблокированным тем же мьютексом. То есть, если один и тот же код потока выполняется в другом экземпляре потока, он блокирует блокировку, тогдаlock()
должен блокировать поток управления там. Это относится к потоку, который использует другой код потока, который также обращается к тем же данным и который также заблокирован тем же мьютексом. В этом случае вы все еще находитесь в процессе доступа к данным, и вам может потребоваться, скажем, еще 15 секунд, чтобы достичь разблокировки мьютекса (чтобы другой поток, блокируемый блокировкой мьютекса, разблокировался и позволил элементу управления доступ к данным). Разрешаете ли вы любой ценой позволить еще одному потоку просто разблокировать тот же мьютекс и, в свою очередь, разрешить потоку, который уже ожидает (блокирует) блокировку мьютекса, разблокировать и получить доступ к данным? Надеюсь, ты понял, что я здесь говорю? Согласно согласованному универсальному определению!
Так что, если вы очень внимательно относитесь к использованию бинарного семафора вместо мьютекса, вам следует быть очень осторожным в «определении» блокировок и разблокировок. Я имею в виду, что каждый поток управления, который затрагивает каждую блокировку, должен вызывать вызов разблокировки, также не должно быть никакой «первой разблокировки», скорее это должна быть всегда «первая блокировка».
Mutex используются для «Механизмов блокировки». один процесс за раз может использовать общий ресурс
в то время как
Семафоры используются для «Сигнальных механизмов», таких как «Я закончил, теперь могу продолжить»
Миф:
Пара статей говорит, что «двоичный семафор и мьютекс одинаковы» или «семафор со значением 1 является мьютексом», но основное отличие в том, что Mutex может быть освобожден только тем потоком, который его получил, в то время как вы можете сигнализировать семафор из любого другого потока
Ключевые моменты:
• Поток может получить более одной блокировки (Mutex).
• Мьютекс может быть заблокирован более одного раза, только если это рекурсивный мьютекс, здесь блокировка и разблокировка для мьютекса должны быть одинаковыми
• Если поток, который уже заблокировал мьютекс, попытается снова заблокировать мьютекс, он войдет в список ожидания этого мьютекса, что приведет к взаимоблокировке.
• Двоичный семафор и мьютекс похожи, но не одинаковы.
• Mutex является дорогостоящей операцией из-за протоколов защиты, связанных с ним.
• Основная цель мьютекса - добиться атомарного доступа или блокировки ресурса.
Мьютекса контролирует доступ к одному общему ресурсу. Он предоставляет операции для получения () доступа к этому ресурсу и выпуска () его по завершении.
Семафор управляет доступом к общему пулу ресурсов. Он обеспечивает операции Wait () до тех пор, пока один из ресурсов в пуле не станет доступным, и Signal () когда он будет возвращен пулу.
Когда количество ресурсов, которые защищает семафор, больше 1, оно называется счетным семафором . Когда он управляет одним ресурсом, он называется булевым семафором . Булев семафор эквивалентен мьютексу.
Таким образом, семафор - это абстракция более высокого уровня, чем Mutex. Mutex может быть реализован с использованием семафора, но не наоборот.
Измененный вопрос - в чем разница между мьютексом и «двоичным» семафором в «Linux»?
Ответ: Ниже приведены различия: i) Область действия. Область действия мьютекса находится в пределах адресного пространства процесса, которое его создало, и используется для синхронизации потоков. Принимая во внимание, что семафор может использоваться в пространстве процессов и, следовательно, он может использоваться для межпроцессной синхронизации.
II) Mutex легкий и быстрее, чем семафор. Futex еще быстрее
iii) Mutex может быть успешно получен одним и тем же потоком несколько раз при условии, что он должен освобождать его одинаковое количество раз. Другой поток, пытающийся получить, заблокирует. Принимая во внимание, что в случае семафора, если тот же процесс пытается получить его снова, он блокируется, поскольку его можно получить только один раз.
Разница между двоичным семафором и мьютексом: ВЛАДЕНИЕ: Семафоры могут сигнализироваться (публиковаться) даже от не текущего владельца. Это означает, что вы можете просто отправлять сообщения из любой другой ветки, хотя вы не являетесь их владельцем.
Семафор - это публичное свойство в процессе, оно может быть просто опубликовано темой, не являющейся владельцем. Пожалуйста, отметьте эту разницу жирным шрифтом, это очень много значит.
Мьютекс работает над блокированием критической области, но семафор работает на счету.
http://www.geeksforgeeks.org/archives/9102 обсуждает в деталях.
Mutex
механизм блокировки, используемый для синхронизации доступа к ресурсу
Semaphore
является сигнальным механизмом.
Это до программиста, если он / она хочет использовать двоичный семафор вместо мьютекса.
Помимо того, что мьютексы имеют владельца, эти два объекта могут быть оптимизированы для различного использования. Мьютексы предназначены для удержания только в течение короткого времени; нарушение этого может привести к снижению производительности и несправедливому планированию. Например, работающему потоку может быть разрешено получить мьютекс, даже если другой поток уже заблокирован на нем. Семафоры могут обеспечить большую справедливость, или справедливость может быть вызвана использованием нескольких условных переменных.
sem_post()
для SCHED_FIFO
и SCHED_RR
(оба из них не по умолчанию): наивысший приоритет потока, и , если есть несколько с тем же приоритетом, нити , которые долго ждали дольше. OpenSolaris в некоторой степени следует этому правилу FIFO даже для обычного планирования. Для glibc и FreeBSD разблокировка простого мьютекса (т.е. не приоритетная защита или наследование приоритетов) и публикация семафора в основном одинаковы, помечая объект как разблокированный, а затем, если могут быть ожидающие потоки, вызывать ядро для пробуждения одного из них.
В окнах разница, как показано ниже. MUTEX: процесс, который успешно выполняет ожидание, должен выполнить сигнал и наоборот. Двоичные семафоры: различные процессы могут выполнять операцию ожидания или сигнала на семафоре.
В то время как двоичный семафор может использоваться как мьютекс, мьютекс является более конкретным вариантом использования, так как только процесс, который заблокировал мьютекс, должен его разблокировать. Это ограничение собственности позволяет обеспечить защиту от:
Эти ограничения не всегда присутствуют, потому что они ухудшают скорость. Во время разработки вашего кода вы можете временно включить эти проверки.
Например, вы можете включить атрибут проверки ошибок в вашем мьютексе. Ошибка проверки мьютексов возвращается, 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");
Концепция была понятна мне после перехода выше постов. Но были некоторые затяжные вопросы. Итак, я написал этот маленький кусочек кода.
Когда мы пытаемся дать семафор, не беря его, он проходит. Но когда вы пытаетесь дать мьютекс, не беря его, это не получается. Я проверил это на платформе 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;
}
Тот факт, что семафор позволяет вам сигнализировать «это сделано с использованием ресурса», даже если он никогда не владел этим ресурсом, заставляет меня думать, что в случае семафоров существует очень слабая связь между владением и передачей сигналов.
Mutex используется для защиты конфиденциального кода и данных, семафор используется для синхронизации. Вы также можете иметь практическое применение для защиты конфиденциального кода, но может существовать риск, что снятие защиты другим потоком выполняется операцией V. Так что Различие между би-семафором и мьютексом является собственностью. Например, в туалете Mutex похож на то, что можно войти в туалет и запереть дверь, никто больше не может войти, пока человек не выйдет, би-семафор похож на того, что можно войти в туалет и запирают дверь, но кто-то еще может войти, попросив администратора открыть дверь, это смешно.
Mutex
Мьютексы обычно используются для сериализации доступа к разделу повторно входящего кода, который не может выполняться одновременно более чем одним потоком. Объект мьютекса позволяет только одному потоку в управляемый раздел, заставляя другие потоки, которые пытаются получить доступ к этому разделу, ждать, пока первый поток не выйдет из этого раздела. Правильное использование мьютекса для защиты общего ресурса может быть опасным непреднамеренный побочный эффект. Любые две задачи RTOS, которые работают с разными приоритетами и координируются через мьютекс, создают возможность для инверсии приоритетов . Mutex работает в пространстве пользователя .
семафор
Семафор - это сигнальный механизм. Семафор ограничивает количество одновременных пользователей общего ресурса до максимального количества. Потоки могут запрашивать доступ к ресурсу (уменьшая семафор) и могут сигнализировать, что они закончили использовать ресурс (увеличивая семафор). Он позволяет нескольким потокам получать доступ к совместно используемым ресурсам. Правильное использование семафора предназначено для передачи сигналов от одной задачи к другой. Семафоры также могут использоваться для передачи сигналов от подпрограммы обработки прерываний (ISR) к задаче. Сигнализация семафора является неблокирующим поведением RTOS и, следовательно, безопасна для ISR. Поскольку этот метод устраняет склонность к ошибкам, необходимо отключать прерывания на уровне задач. Это работает в пространстве ядра .
Ответ может зависеть от целевой ОС. Например, по крайней мере одна из знакомых мне реализаций RTOS позволит выполнять несколько последовательных операций «get» для одного мьютекса ОС, при условии, что все они находятся в одном и том же контексте потока. Множественное получение должно быть заменено равным количеством операций, прежде чем другому потоку будет разрешено получить мьютекс. Это отличается от двоичных семафоров, для которых допускается только одно получение, независимо от контекста потока.
Идея такого мьютекса заключается в том, что вы защищаете объект, позволяя изменять данные только в одном контексте. Даже если поток получает мьютекс и затем вызывает функцию, которая дополнительно изменяет объект (и получает / помещает мьютекс защитника вокруг своих собственных операций), операции все равно должны быть безопасными, поскольку все они происходят в одном потоке.
{
mutexGet(); // Other threads can no longer get the mutex.
// Make changes to the protected object.
// ...
objectModify(); // Also gets/puts the mutex. Only allowed from this thread context.
// Make more changes to the protected object.
// ...
mutexPut(); // Finally allows other threads to get the mutex.
}
Конечно, при использовании этой функции вы должны быть уверены, что все обращения в пределах одного потока действительно безопасны!
Я не уверен, насколько распространен этот подход или применяется ли он за пределами систем, с которыми я знаком. Пример такого мьютекса см. В RTOS ThreadX.
Мьютексы имеют право собственности, в отличие от семафоров. Хотя любой поток в рамках мьютекса может получить разблокированный мьютекс и заблокировать доступ к тому же критическому разделу кода, только поток, заблокировавший мьютекс, должен разблокировать его .
Как уже упоминали многие, мьютекс используется для защиты критического фрагмента кода (критический раздел AKA). Вы получите мьютекс (блокировку), войдите в критический раздел и освободите мьютекс (разблокировку) в одном потоке .
При использовании семафора вы можете заставить поток ждать семафор (скажем, поток A), пока другой поток (скажем, поток B) не выполнит какую-либо задачу, а затем установить семафор для потока A, чтобы остановить ожидание и продолжить свою задачу.
Лучшее решение
Единственная разница
1.Mutex -> блокировка и разблокировка находятся в собственности потока, который блокирует мьютекс.
2. Семафор -> Нет собственности т.е. если один поток вызывает semwait (s), любой другой поток может вызвать sempost (s), чтобы снять блокировку.
MUTEX
До недавнего времени единственным спящим замком в ядре был семафор. Большинство пользователей семафоров создавали семафор со счетчиком один и рассматривали их как блокировку взаимного исключения - спящую версию спин-блокировки. К сожалению, семафоры являются довольно общими и не накладывают никаких ограничений на использование. Это делает их полезными для управления эксклюзивным доступом в непонятных ситуациях, таких как сложные танцы между ядром и пользовательским пространством. Но это также означает, что более простую блокировку сделать труднее, а отсутствие принудительных правил делает невозможным любой вид автоматической отладки или применения ограничений. В поисках более простого спящего замка разработчики ядра представили мьютекс. Да, как вы уже привыкли, это запутанное имя. Давайте уточним. Термин «мьютекс» - это общее имя для обозначения любого спящего замка, который обеспечивает взаимное исключение, такой как семафор со счетчиком использования одного. В последних ядрах Linux собственное существительное «mutex» теперь также является особым типом спящего замка, который реализует взаимное исключение. То есть мьютекс - это мьютекс.
Простота и эффективность мьютекса проистекают из дополнительных ограничений, которые он накладывает на своих пользователей сверх того, что требует семафор. В отличие от семафора, который реализует самое основное поведение в соответствии с оригинальным дизайном Дейкстры, мьютекс имеет более строгий и узкий вариант использования: n Одновременно только одна задача может содержать мьютекс. То есть счетчик использования мьютекса всегда один.
[1] Разработка ядра Linux, третье издание Роберт Лав
Я думаю, что большинство ответов здесь сбивают с толку, особенно те, которые говорят, что мьютекс может быть освобожден только процессом, который его удерживает, но семафор может сигнализироваться любым процессом. Приведенная выше строка является довольно размытой с точки зрения семафора. Чтобы понять, мы должны знать, что существует два вида семафоров: один называется счетным семафором, а другой - двоичным семафором. При подсчете семафор обрабатывает доступ к n количеству ресурсов, где n может быть определено перед использованием. Каждый семафор имеет переменную count, которая хранит счетчик количества используемых ресурсов, изначально он равен n. Каждый процесс, который хочет использовать ресурс, выполняет операцию wait () с семафором (тем самым уменьшая количество). Когда процесс освобождает ресурс, он выполняет операцию release () (увеличивая счетчик). Когда счет становится 0, все ресурсы используются. После этого процесс ожидает, пока счетчик станет больше 0. Теперь здесь есть перехват, только процесс, который содержит ресурс, может увеличить счет, никакой другой процесс не может увеличить счет, только процессы, содержащие ресурс, могут увеличить счет и процесс. ожидание семафора снова проверяет, и когда он видит доступный ресурс, он снова уменьшает количество. Таким образом, с точки зрения бинарного семафора, только процесс, содержащий семафор, может увеличить счетчик, и счет остается нулевым, пока он не прекратит использовать семафор и не увеличит счет, и другой процесс получит возможность доступа к семафору. Теперь здесь есть ловушка, только процесс, который содержит ресурс, может увеличить счетчик, никакой другой процесс не может увеличить счет, только процесс, содержащий ресурс, может увеличить счетчик, и процесс, ожидающий семафор, снова проверяет, и когда он видит ресурс, доступный, это уменьшает счет снова. Таким образом, с точки зрения бинарного семафора, только процесс, содержащий семафор, может увеличить счетчик, и счет остается нулевым, пока он не прекратит использовать семафор и не увеличит счет, и другой процесс получит возможность доступа к семафору. Теперь здесь есть ловушка, только процесс, который содержит ресурс, может увеличить счетчик, никакой другой процесс не может увеличить счет, только процесс, содержащий ресурс, может увеличить счетчик, и процесс, ожидающий семафор, снова проверяет, и когда он видит ресурс, доступный, это уменьшает счет снова. Таким образом, с точки зрения бинарного семафора, только процесс, содержащий семафор, может увеличить счетчик, и счет остается нулевым, пока он не прекратит использовать семафор и не увеличит счет, и другой процесс получит возможность доступа к семафору.
Основное различие между двоичным семафором и мьютексом заключается в том, что семафор является сигнальным механизмом, а мьютекс - механизмом блокировки, но двоичный семафор, по-видимому, функционирует как мьютекс, что создает путаницу, но оба представляют собой разные концепции, подходящие для разных видов работы.