Обсуждение:Мьютекс

message: CreateMutex/ReleaseMutex - функции WinAPI. Поэтому некорректно приводить их в тексте, говоря при этом, что это системные вызовы. При том еще ссылаясь в дальнейшем, что в каждой ОС свои функции. Т.о. получилась каша. 95.158.255.179 09:44, 15 декабря 2010 (UTC)
replies: text: Переделал с обобщением. Так лучше? Netch 08:00, 20 декабря 2010 (UTC)

message: В первом абзаце нет упоминания атрибута "владелец", основного отличия мьютекса от семафора. А это отличие фундаментально в том смысле, что многие алгоритмы построенные на основе семафоров не могут быть реализованы с использованием мьютексов (точнее только с использованием мьютексов без других средств синхронизации).
Например, ISO/IEC 14882:2011(E) (C++11), даёт следующее определение мьютекса исходя из его свойств:
A mutex object facilitates protection against data races and allows safe synchronization of data between execution agents (30.2.5). An execution agent owns a mutex from the time it successfully calls one of the lock functions until it calls unlock. Mutexes can be either recursive or non-recursive, and can grant simultaneous ownership to one or many execution agents. The mutex types supplied by the standard library provide exclusive ownership semantics: only one thread may own the mutex at a time. Both recursive and non-recursive mutexes are supplied.
Конечно, чаще всего мы имеем дело с обычными мьютексами (Си11, C++11, POSIX, WinAPI), которые похожи на "одноместный" семафор. Однако мьютексы значительно проще в реализации на типичных платформах, чем семафоры.
Кроме того, все (или подавляющее большинство реализаций) поддерживают так же "рекурсивные мьютексы", которые уже обладают немного более сложной структурой и уже совсем не похожи на семафоры.
Так же встречается использование понятия "разделяемый мьютекс" (Boost), который обеспечивает возможности, как эксклюзивной принадлежности одному потоку для модификации данных, так и совместного владения несколькими потоками только для чтения данных.
Итого предлагается дать следующую формулировку первого абзаца, основанную только на предназначении и свойствах мьютекса:
Мью́текс (, от  — "взаимное исключение") — программный объект предназначенный для исключения состояния гонок и безопасной синхронизации одновременно выполняющихся потоков определённым образом обращающихся к совместным данным.
Сергей Леонтьев, Крипто-Про 22:57, 4 февраля 2013 (UTC)
* Всё слишком путано получается с мьютексами. По части теории классически они определяются именно как эксклюзивное владение блокировкой и именно между потоками. Но в реализациях мьютексами могут назвать, насколько понимаю, и бинарные семафоры, и блокировки чтения-записи, иногда и спин-блокировки, что стирает границы между разными примитивами и алгоритмами. Предлагаю всё же рассматривать shared mutex'ы в рамках блокировок чтения-записи, а в базовом определении мьютекса описать классический примитив синхронизации, отдельно сделав говорки. Или дать два определения, одно — классическое, а другое — обобщающее. -- D6194c-1cc (обс.) 20:13, 20 июня 2020 (UTC)
** std::shared_mutex предназначен для ассоциации с std::conditional_variable_any, поэтому их в стандарте и назвали "мьютексами", а, скажем, POSIX блокировки чтения/записи (pthread_rwlock_*()) не имеют таковой ассоциации с условными переменными и не имеют слова "мьютекс" в своём названии Сергей Леонтьев, Крипто-Про (обс.) 02:20, 21 июня 2020 (UTC)
* Касательно общих или разделяемых мьютексов сделал оговорку в базовом определении. -- D6194c-1cc (обс.) 20:43, 20 июня 2020 (UTC)
** Участник:D6194c-1cc, Ваша правка https://ru.wikipedia.org/w/index.php?title=Мьютекс&diff=prev&oldid=107757133 с заменой "Мьютекс отличается от спинлока тем, что планировщик переводит ожидающие доступа к мьютексу потоки в пассивное состояние" на "От спинлока мьютекс отличается передачей управления планировщику при невозможности захвата мьютекса потоком" немного неточна, т.к. практически все современные спинлоки используют инструкции типа SMT PAUSE (REP NOP, для x86, т.е. обращаются к "аппаратному планировщику"), но часто ж они обращаются и к "планировщику потоков", скажем, FreeBSD pthread_spin_lock() вызывает pthread_yield(), а Solaris pthread_spin_lock() вызывает no_preempt(self)/preempt(self). Сергей Леонтьев, Крипто-Про (обс.) 02:03, 21 июня 2020 (UTC)
*** Я не знаю, что там за особенная модификация glibc в FreeBSD или Solaris, но в исходниках glibc для разных архитектур обычная спин-блокировка с активным ожиданием. NOP тоже смысла не имеет, поскольку нет смысла заменять рабочий код на пустышку, это не даёт никаких преимуществ, а вот задержки добавит. И про какие-либо «аппаратные планировщики» я никогда не слышал, процессор просто «последовательно» исполняет код, а его внутренняя кухня нам уже не интересна. Если заменить в спин-блокировке активное ожидание на обращение к планировщику, это уже мьютекс получится, а не спин-блокировка. -- D6194c-1cc (обс.) 07:38, 21 июня 2020 (UTC)
*** Про PAUSE почитал немного, это не более чем подсказка процессору для оптимизации его работы, к планировщику не имеет отношения. -- D6194c-1cc (обс.) 07:52, 21 июня 2020 (UTC)
**** Ну как не имеет, по этой команде, ядро процессора переключается на соседний поток "гипертрединга" (или соседние потоки, для Sparc/Power/Intel Xeon Phi). Сергей Леонтьев, Крипто-Про (обс.) 09:05, 21 июня 2020 (UTC)
***** Внутренняя реализация нас не интересует, и никто никуда не переключается, что за заявления? Гипертрединг работает по принципу распараллеливания некоторых инструкций, причём тут PAUSE?
**** FreeBSD, Solaris, как и macOS с Windows, в базовых вариантах glibc не имеют, а вот спинлоки имеют. И они устроены, естественно, немного иначе и немного лучше, чем в glibc. В частности, FreeBSD pthread_spin_lock() вызывает pthread_yield() практически сразу, в случае если выделен один процессор, либо через 10000 итераций ожидания, в случае если выделено несколько процессоров. В libc Solaris у спинлоков есть свои фокусы с планировщиком, ввиду реализации многопоточности вида M*N.
***** Боюсь, что для подобных противоречащих здравому смыслу утверждений про реализации pthreads необходимо предъявить источники (ссылка на сорцы или специализированные форки, или что у Вас там). -- D6194c-1cc (обс.) 10:49, 21 июня 2020 (UTC)
**** Поэтому некорректно разделять мьютексы и спинлоки "по обращению к планировщику", в общем случае и те и другие обращаются, только за разным. А корректное и важное различие состоит в том, что используется ли "активное ожидание" или "пассивное ожидание", т.к. по этой причине мьютексы нельзя использовать в обработчиках сигналов и прерываний, а спинлоки можно, хотя и осторожно. Сергей Леонтьев, Крипто-Про (обс.) 09:05, 21 июня 2020 (UTC)
***** Во время активного ожидания обращение к планировщику происходит разве что при переключении контекста, но это не в самой реализации спин-блокировки, а на уровне ОС, поэтому в расчёт это брать нет необходимости. Пассивное же ожидание слишком размытый термин, на мой взгляд, и так или иначе предполагает планировщик. -- D6194c-1cc (обс.) 10:49, 21 июня 2020 (UTC)
thread_title:  Неточное определение мьютекса в первом абзаце 

message: Мьютекс создаёт взаимоисключающий доступ, т.е. только одному потоку, семафоры создают доступ более одному потоку, при этом есть счетчик, у мьютикса его нет. Плюс у мьютекса есть понятие владельца. Вот еще:
http://blog.feabhas.com/2009/09/mutex-vs-semaphores-%E2%80%93-part-1-semaphores/
http://www.barrgroup.com/Embedded-Systems/How-To/RTOS-Mutex-Semaphore
 46.251.75.242 16:09, 20 августа 2013 (UTC) Евгений Евгеньевич
thread_title:  Мьютекс это не семафор 

message: Подраздел "На уровне операционных систем" описывает состояние дел только для Linux, в Windows, FreeBSD, Solaris и AIX имеются кардинальные отличия.
Подразделы "В архитектурах x86 и x86_64" и "В архитектуре ARM", по сути, описывают спин-блокировки. Оговорка "Передача управления планировщику является достаточно быстрой операцией..." ошибочна, особенно ввиду того, что в одном цикле ожидания она может происходить многократно. Этот метод реализации мютекса практически не применяется.
Предлагаю:
* Подразделы "В архитектурах x86 и x86_64" и "В архитектуре ARM" перенести в спин-блокировки;
* Подраздел "На уровне операционных систем", либо расширить, либо вообще удалить раздел "Детали реализации", как устаревший и не имеющий фундаментальную ценность.
Сергей Леонтьев, Крипто-Про (обс.) 10:44, 31 августа 2021 (UTC)
* Нет, задумка раздела была в том, чтобы показать, как мьютексы реализуются на уровне операционной системы и на уровне процессора. Это цельный раздел, который должен подводить читателя с более высокого уровня в более низкий. Если мы не смогли захватить блокировку атомарно, то процесс/поток уже на уровне механизмов ОС попадает в список ожидающих. Аналогично, если блокировка снимается, сигнализируются ожидающие задачи. Механизм сигнализации к спин-локам не относится. -- D6194c-1cc (обс.) 18:17, 31 августа 2021 (UTC)
** Два вопроса: это кому-нибудь нужно? Поясню, свойства мьютексов (такие как: справедливость при захвате или случайность, инверсия приоритетов и т.п.) определяются планировщиком ОС (или в Solaris и некоторых версиях FreeBSD для потоков N*M, ещё и планировщиком потоков), поэтому, в отличие от спин-блокировок не возникает особой необходимости создавать собственные мьютексы на коленке. Да, даже если и возникает, то эта работа связана с подробным погружением в потроха ОС. А вот в разделе спин-блокировок это дело пока полезное, т.к. пока ни в одном API нет всех полезных вариантов спин-блокировок. Сергей Леонтьев, Крипто-Про (обс.) 09:27, 2 сентября 2021 (UTC)
** И достаточен ли уровень изложения? Пока этот раздел, позволяет реализовать на коленке только спин-блокировку, да и то без управления видимостью изменений (кэшами процессоров и std::memory_order). Сергей Леонтьев, Крипто-Про (обс.) 09:27, 2 сентября 2021 (UTC)
* Кстати, пример мьютекса с XCHG: . -- D6194c-1cc (обс.) 18:41, 31 августа 2021 (UTC)
thread_title:  Проблемы раздела "Детали реализации" 

message: Сейчас в статье в нескольких местах используются, на мой взгляд, совершенно излишние оговорки вида: "разделяемых мьютексов — shared_mutex и shared_timed_mutex[4], — по факту являющихся блокировками чтения-записи". 
Во-первых, в начале статьи это уже указано, что есть такие мьютексы (так называемые "классические"), есть сякие мьютексы (рекурсивные, разделяемые и т.п.), и от повторения читатель не получает никакой дополнительной информации.
Во-вторых, мьютекс - это термин, который уже эволюционировал от словосочетания "mutual exclusion", и, на настоящий момент, имеет свой собственный смысл.
Во-третьих, собственно тот же самый вопрос можно поставить относительно Python lock, C++ std::lock, тех же критических секций Win32 и др., варианты:
# Нечто является мьютексом, если в АИ называется мьютексом - нормальный подход;
# Нечто является мьютексом, если является пассивной эксклюзивной блокировкой имеющей владельца - ненормальный подход, т.к. и, скорее всего, противоречит АИ, и скорее всего, содержит элементы ОРИСС (мы же сами оцениваем выполнение совокупности этих свойств);
# Нечто является мьютексом, если является пассивной блокировкой имеющей владельца и может ассоциироваться с условной переменной (conditional variable) - пока неясный подход, т.к. содержит элементы ОРИСС (можно заметить, что связь мьютексов с условными переменными весьма важна).
Получается, что:
* Python Lock/RLoc ввиду возможной ассоциации с Condition - наверное, можно назвать мьютексами по пп. 2 и 3;
* Win32 CRITICAL_SECTION (начиная с Vista/W2r8) ввиду SleepConditionVariableCS() - наверное, тоже можно назвать мьютексами по пп. 2 и 3;
* Win32 SRWLOCK - не знаю, выполняется только п. 3. Я бы назвал его разделяемым мьютексом, но...;
* С++ std::shared_mutex - однозначно разделяемый мьютекс по пп. 1 и 3;
* POSIX pthread_rwlock_t - однозначно не является мьютексом, т.к. не выполняется ни один из пунктов.
- Сергей Леонтьев, Крипто-Про (обс.) 08:57, 2 сентября 2021 (UTC)
thread_title:  Чем мьютексы отличаются от блокировок?