Мьютекс - это концепция программирования, которая часто используется для решения многопоточных задач. Мой вопрос к сообществу:
Что такое мьютекс и как вы его используете?
Мьютекс - это концепция программирования, которая часто используется для решения многопоточных задач. Мой вопрос к сообществу:
Что такое мьютекс и как вы его используете?
Ответы:
Когда на работе я веду бурную дискуссию, я использую резинового цыпленка, которого держу в своем столе именно для таких случаев. Человек, держащий курицу, является единственным человеком, которому разрешено говорить. Если вы не держите курицу, вы не можете говорить. Вы можете только указать, что хотите курицу, и подождать, пока вы ее получите, прежде чем говорить. Как только вы закончите говорить, вы можете вернуть курицу модератору, который передаст ее следующему человеку, который будет говорить. Это гарантирует, что люди не разговаривают друг с другом, а также имеют свое собственное пространство для общения.
Замените Цыпленка на Мьютекс, а человека - на нить, и у вас в основном будет концепция мьютекса.
Конечно, не существует такого понятия, как резиновый мьютекс. Только резиновая курица. У моих кошек когда-то была резиновая мышь, но они ее съели.
Конечно, прежде чем использовать резиновую курицу, вам нужно спросить себя, нужно ли вам на самом деле 5 человек в одной комнате, и не будет ли проще, когда один человек в комнате сам выполняет всю работу. На самом деле, это просто продолжение аналогии, но вы поняли идею.
Мьютекс - это взаимоисключающий флаг. Он действует как привратник к разделу кода, позволяя одному потоку входить и блокируя доступ ко всем остальным. Это гарантирует, что контролируемый код будет обрабатываться только одним потоком за раз. Просто не забудьте освободить мьютекс, когда закончите. :)
Взаимное исключение. Вот запись в Википедии:
http://en.wikipedia.org/wiki/Mutual_exclusion
Задача мьютекса - синхронизировать два потока. Когда два потока пытаются получить доступ к одному ресурсу, общая схема состоит в том, чтобы первый блок кода пытался получить доступ для установки мьютекса перед вводом кода. Когда второй блок кода пытается получить доступ, он видит, что мьютекс установлен, и ждет, пока первый блок кода не завершится (и отменяет установку мьютекса), а затем продолжает.
Конкретные детали того, как это достигается, очевидно, сильно зависит от языка программирования.
Когда у вас многопоточное приложение, разные потоки иногда совместно используют общий ресурс, такой как переменная или аналогичный. К этому общему источнику часто нельзя получить доступ одновременно, поэтому необходима конструкция, чтобы гарантировать, что только один поток использует этот ресурс одновременно.
Эта концепция называется «взаимное исключение» (сокращение Mutex) и позволяет гарантировать, что в этой области разрешен только один поток с использованием этого ресурса и т. Д.
Как их использовать, зависит от языка, но часто (если не всегда) основывается на мьютексе операционной системы.
Некоторые языки не нуждаются в этой конструкции из-за парадигмы, например, функционального программирования (хорошие примеры - Haskell, ML).
В C # распространенным мьютексом является Monitor . Тип « System.Threading.Monitor ». Это также может быть использовано неявно через оператор ' lock (Object) '. Одним из примеров его использования является создание класса Singleton.
private static readonly Object instanceLock = new Object();
private static MySingleton instance;
public static MySingleton Instance
{
lock(instanceLock)
{
if(instance == null)
{
instance = new MySingleton();
}
return instance;
}
}
Оператор lock, использующий объект private lock, создает критический раздел. Требование к каждому потоку дождаться окончания предыдущего. Первый поток войдет в раздел и инициализирует экземпляр. Второй поток будет ждать, попасть в раздел и получить инициализированный экземпляр.
Любой вид синхронизации статического члена может использовать оператор блокировки аналогично.
Что такое мьютекс ?
Мьютекс (фактически термин мьютекс - это сокращение от взаимного исключения), также известный как спин-блокировка, является самым простым инструментом синхронизации, который используется для защиты критических областей и, таким образом, предотвращения условий гонки. То есть поток должен получить блокировку перед входом в критический раздел (в критическом разделе несколько потоков совместно используют общую переменную, обновление таблицы, запись файла и т. Д.), Он снимает блокировку, когда покидает критический раздел.
Что такое состояние гонки ?
Состояние гонки возникает, когда два или более потоков могут получить доступ к общим данным, и они пытаются изменить их одновременно. Поскольку алгоритм планирования потоков может переключаться между потоками в любое время, вы не знаете порядок, в котором потоки будут пытаться получить доступ к общим данным. Следовательно, результат изменения данных зависит от алгоритма планирования потоков, то есть оба потока «участвуют в гонке», чтобы получить доступ / изменить данные.
Пример из реальной жизни:
Когда на работе я веду бурную дискуссию, я использую резинового цыпленка, которого держу в своем столе именно для таких случаев. Человек, держащий курицу, является единственным человеком, которому разрешено говорить. Если вы не держите курицу, вы не можете говорить. Вы можете только указать, что хотите курицу, и подождать, пока вы ее получите, прежде чем говорить. Как только вы закончите говорить, вы можете вернуть курицу модератору, который передаст ее следующему человеку, который будет говорить. Это гарантирует, что люди не разговаривают друг с другом, а также имеют свое собственное пространство для общения.
Замените Цыпленка на Мьютекс, а человека - на нить, и у вас в основном будет концепция мьютекса.
@Xetius
Использование в C #:
В этом примере показано, как локальный объект Mutex используется для синхронизации доступа к защищенному ресурсу. Поскольку каждый вызывающий поток блокируется до тех пор, пока не получит право собственности на мьютекс, он должен вызвать метод ReleaseMutex, чтобы освободить право собственности на поток.
using System;
using System.Threading;
class Example
{
// Create a new Mutex. The creating thread does not own the mutex.
private static Mutex mut = new Mutex();
private const int numIterations = 1;
private const int numThreads = 3;
static void Main()
{
// Create the threads that will use the protected resource.
for(int i = 0; i < numThreads; i++)
{
Thread newThread = new Thread(new ThreadStart(ThreadProc));
newThread.Name = String.Format("Thread{0}", i + 1);
newThread.Start();
}
// The main thread exits, but the application continues to
// run until all foreground threads have exited.
}
private static void ThreadProc()
{
for(int i = 0; i < numIterations; i++)
{
UseResource();
}
}
// This method represents a resource that must be synchronized
// so that only one thread at a time can enter.
private static void UseResource()
{
// Wait until it is safe to enter.
Console.WriteLine("{0} is requesting the mutex",
Thread.CurrentThread.Name);
mut.WaitOne();
Console.WriteLine("{0} has entered the protected area",
Thread.CurrentThread.Name);
// Place code to access non-reentrant resources here.
// Simulate some work.
Thread.Sleep(500);
Console.WriteLine("{0} is leaving the protected area",
Thread.CurrentThread.Name);
// Release the Mutex.
mut.ReleaseMutex();
Console.WriteLine("{0} has released the mutex",
Thread.CurrentThread.Name);
}
}
// The example displays output like the following:
// Thread1 is requesting the mutex
// Thread2 is requesting the mutex
// Thread1 has entered the protected area
// Thread3 is requesting the mutex
// Thread1 is leaving the protected area
// Thread1 has released the mutex
// Thread3 has entered the protected area
// Thread3 is leaving the protected area
// Thread3 has released the mutex
// Thread2 has entered the protected area
// Thread2 is leaving the protected area
// Thread2 has released the mutex
Здесь есть несколько отличных ответов, вот еще одна замечательная аналогия для объяснения того, что такое мьютекс :
Рассмотрим один туалет с ключом . Когда кто-то входит, они берут ключ и туалет занят . Если кому-то еще нужно пользоваться туалетом, ему нужно ждать в очереди . Когда человек в туалете сделан , он передает ключ следующему человеку в очереди. Имеет смысл, верно?
Преобразуйте туалет в истории в общий ресурс и ключ к мьютексу . Взяв ключ от туалета (приобретите замок), вы сможете его использовать. Если ключа нет (замок заблокирован), вам придется подождать. Когда ключ возвращается человеком ( снимите блокировку ), вы можете получить его сейчас.
Чтобы понять MUTEX, сначала вам нужно знать, что такое «состояние гонки», и только тогда вы поймете, зачем нужен MUTEX. Предположим, у вас есть многопоточная программа и два потока. Теперь у вас есть одна работа в очереди. Первый поток проверит очередь заданий и, найдя задание, начнет ее выполнять. Второй поток также проверит очередь заданий и обнаружит, что в очереди есть одно задание. Таким образом, он также назначит тот же указатель задания. Итак, что теперь происходит, оба потока выполняют одну и ту же работу. Это приведет к ошибке сегментации. Это пример состояния гонки.
Решением этой проблемы является MUTEX. MUTEX - это своего рода блокировка, которая блокирует один поток за раз. Если другой поток хочет заблокировать его, он просто блокируется.
Тема MUTEX в этой ссылке на файл PDF действительно стоит прочитать.
Мьютексы полезны в ситуациях, когда вам необходимо обеспечить исключительный доступ к ресурсу для нескольких процессов, когда обычная блокировка не поможет, поскольку она работает только для потоков.
Mutex: Mutex означает Mut ual Ex clusion. Это означает, что одновременно один процесс / поток может войти в критическую секцию. В параллельном программировании, когда несколько потоков / процессов пытаются обновить общий ресурс (любая переменная, общая память и т. Д.), Может привести к неожиданному результату. (Как результат зависит от того, какой поток / процесс получает первый доступ).
Чтобы избежать такого неожиданного результата, нам нужен механизм синхронизации, который гарантирует, что только один поток / процесс получает доступ к такому ресурсу одновременно.
Библиотека pthread обеспечивает поддержку Mutex.
typedef union
{
struct __pthread_mutex_s
{
***int __lock;***
unsigned int __count;
int __owner;
#ifdef __x86_64__
unsigned int __nusers;
#endif
int __kind;
#ifdef __x86_64__
short __spins;
short __elision;
__pthread_list_t __list;
# define __PTHREAD_MUTEX_HAVE_PREV 1
# define __PTHREAD_SPINS 0, 0
#else
unsigned int __nusers;
__extension__ union
{
struct
{
short __espins;
short __elision;
# define __spins __elision_data.__espins
# define __elision __elision_data.__elision
# define __PTHREAD_SPINS { 0, 0 }
} __elision_data;
__pthread_slist_t __list;
};
#endif
Это структура для типа данных мьютекса, т.е. pthread_mutex_t. Когда мьютекс заблокирован, __lock установлен на 1. Когда он разблокирован, __lock установлен на 0.
Это гарантирует, что никакие два процесса / потока не могут получить доступ к критическому разделу одновременно.