Що таке мутекс?


653

Мутекс - це концепція програмування, яка часто використовується для розв’язання задач, що мають багато ниток. Моє запитання до громади:

Що таке мутекс і як ним користуватися?


2
Ось хороша стаття про різницю: barrgroup.com/Embedded-Systems/How-To/RTOS-Mutex-Semaphore
Адам Девіс

Навчальний посібник з mutex може допомогти прояснити речі: stackoverflow.com/questions/4989451/mutex-example-tutorial
Nav

1
Мутекс - це ключ від ванної кімнати на АЗС, гарантуючи, що тільки одна людина може користуватися ванною кімнатою одночасно І що ніхто інший не може користуватися туалетом, поки поточний мешканець не закінчиться і ключ не повернеться.
jonschlinkert

Відповіді:


2152

Коли у мене велика гаряча дискусія на роботі, я використовую гумову курку, яку я тримаю в своєму столі просто для таких випадків. Особа, яка тримає курку, - єдина людина, якій дозволено розмовляти. Якщо ви не тримаєте курку, ви не можете говорити. Ви можете лише вказати, що хочете курку, і чекати, поки ви її отримаєте, перш ніж говорити. Після того, як ви закінчите говорити, ви можете передати курку назад модератору, який передасть її наступній людині, щоб говорити. Це гарантує, що люди не говорять один над одним, а також мають свій простір для розмови.

Замініть курку на Mutex та людину ниткою, і ви, в основному, маєте поняття мютекс.

Звичайно, немає такого поняття, як гумова мутекс. Тільки гумова курка. У моїх котів колись була гумова миша, але вони її їли.

Звичайно, перед тим, як використовувати гумову курку, потрібно запитати себе, чи вам насправді потрібно 5 людей в одній кімнаті, і чи не просто було б просто з однією людиною в кімнаті самостійно виконати всю роботу. Власне, це лише розширення аналогії, але ви отримуєте думку.


9
Чудова відповідь. Чи можна стверджувати, що Mutex - це насправді правила, які зупиняють передачу курки? а курка - це те, що ти замикаєш?
SirYakalot

3
@SirYakalot, ти маєш на увазі курку - ресурс, а модератором - мютекс?
Оуен

156
Курка - мютекс . Люди, що шикують му .. курка, змагаються нитками . Модератором є ОС . Коли люди просять курку, вони роблять запит на замок. Коли ви викликаєте mutex.lock (), ваш потік зупиняється в lock () і робить запит блокування в ОС. Коли ОС виявить, що мютекс був звільнений з потоку, він просто передає його вам, а lock () повертається - мютекс тепер ваш і лише ваш. Ніхто більше не може його вкрасти, тому що виклик lock () заблокує його. Існує також try_lock (), який заблокує та поверне true, коли mutex буде вашим та негайно помилковим, якщо використовується mutex.
Петър Петров

4
Ти геній. Чи можете ви використовувати гумову металеву курку для пояснення моніторів?
Ріккардо

98
Іноді походження деяких програм програмування незрозуміле. Новачок може ходити навколо, цікавлячись, чому всі говорять про регулярний вираз. Не очевидно, що регулярний вираз короткий для [reg] ular [ex] пресування. Аналогічно, мютекс короткий для [мут] уал [колишній] вилучення. Це може полегшити засвоєння значення цього терміна. @TheSmurf посилався на це у своїй відповіді, але, можливо, було б добре додати його тут для історичних цілей.
Доджі Дзакума

137

Mutex - прапор взаємовиключного. Він виконує функцію захисника до розділу коду, що дозволяє ввести один потік і перекрити доступ до всіх інших. Це гарантує, що керований код буде одночасно потрапляти лише одним потоком. Просто не забудьте випустити мютекс, коли закінчите. :)


10
Мютекс сам по собі не має нічого спільного з розділом коду, він захищає деякий ресурс. Цей ресурс може бути кодовим сегментом, якщо мютекс використовується коли-небудь навколо цього коду, але, як тільки ви почнете використовувати мутекс у кількох місцях вашого коду, ваше пояснення не вдасться. Зазвичай він також може бути використаний для захисту деякої структури даних, до якої можна отримати доступ з багатьох місць коду.
paxdiablo

72

Взаємовиключення. Ось запис у Вікіпедії на ній:

http://en.wikipedia.org/wiki/Mutual_exclusion

Суть мутексу - синхронізація двох потоків. Коли у вас є два потоки, які намагаються отримати доступ до одного ресурсу, загальною схемою є перший блок коду, який намагається отримати доступ для встановлення mutex перед введенням коду. Коли другий блок коду намагається отримати доступ, він бачить, що mutex встановлений і чекає, поки перший блок коду буде завершений (і скасує мутекс), а потім продовжується.

Конкретні деталі того, як це здійснюється, очевидно сильно різняться залежно від мови програмування.


65

Коли у вас є багатопотокова програма, різні потоки іноді мають спільний ресурс, наприклад змінну чи подібний. До цього спільного джерела часто не можна одночасно звертатися, тому потрібна конструкція, яка забезпечує лише один потік, який використовує цей ресурс одночасно.

Концепція називається "взаємне виключення" (короткий Mutex), і це спосіб забезпечити, щоб всередині цієї області було дозволено лише одну нитку, використовуючи цей ресурс тощо.

Як ними користуватися, залежить від мови, але часто (якщо не завжди) базується на мутексі операційної системи.

Деяким мовам ця конструкція не потрібна через парадигму, наприклад, функціональне програмування (Haskell, ML - хороші приклади).


26

У C # поширений мутекс - це Монітор . Тип - " 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;
    }
}

Оператор блокування за допомогою об'єкта приватного блокування створює критичний розділ. Вимагаючи від кожної нитки зачекати, поки попередній не буде закінчений. Перший потік увійде в розділ і ініціалізує екземпляр. Другий потік зачекає, потрапить у розділ та отримає ініціалізований екземпляр.

Будь-який тип синхронізації статичного члена може використовувати оператор блокування аналогічно.


1
Це відповідь, що залежить від реалізації. Також у CS монітор відрізняється від mutex. Монітори мають механізм синхронізації, але mutex просто блокує річ, поки вона більше не потрібна. IDK про деталі реалізації або семантику C #, але я думаю, що контекст питання ширший
marcoslhc

24

Що таке Мутекс ?

Мутекс (насправді, термін mutex короткий для взаємного виключення) також відомий як спінлок - це найпростіший інструмент синхронізації, який використовується для захисту критичних областей і, таким чином, запобігання перегонів. Тобто потік повинен придбати замок перед входом у критичний розділ (У критичному розділі багато потоків мають спільну змінну, оновлення таблиці, написання файлу тощо), він випускає блокування, коли залишає критичний розділ.

Що таке перегони ?

Умова перегонів виникає, коли два або більше потоків можуть отримати доступ до спільних даних і вони намагаються змінити їх одночасно. Оскільки алгоритм планування потоків може змінюватися між потоками в будь-який час, ви не знаєте, в якому порядку потоки будуть намагатися отримати доступ до спільних даних. Отже, результат зміни даних залежить від алгоритму планування потоків, тобто обидва потоки "гоняться" для доступу / зміни даних.

Приклад із реального життя:

Коли у мене велика гаряча дискусія на роботі, я використовую гумову курку, яку я тримаю в своєму столі просто для таких випадків. Особа, яка тримає курку, - єдина людина, якій дозволено розмовляти. Якщо ви не тримаєте курку, ви не можете говорити. Ви можете лише вказати, що хочете курку, і чекати, поки ви її отримаєте, перш ніж говорити. Після того, як ви закінчите говорити, ви можете передати курку назад модератору, який передасть її наступній людині, щоб говорити. Це гарантує, що люди не говорять один над одним, а також мають свій простір для розмови.

Замініть курку на Mutex та людину ниткою, і ви, в основному, маєте поняття мютекс.

@Xetius

Використання в C #:

Цей приклад показує, як локальний об’єкт Mutex використовується для синхронізації доступу до захищеного ресурсу. Оскільки кожен потік виклику блокується, поки він не набуде права власності на 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

MSDN Reference Mutex


1
дуже хороший приклад
Siwei Shen

22

Тут є кілька чудових відповідей, ось ще одна чудова аналогія для пояснення, що таке мутекс :

Розглянемо одиночний туалет з ключем . Коли хтось заходить, вони беруть ключ і туалет зайнятий . Якщо комусь потрібно скористатися туалетом, їм потрібно чекати в черзі . Коли людина в туалеті зроблена , вони передають ключ черговій людині в черзі. Має сенс, правда?

Перетворіть туалет у сюжеті на загальний ресурс та ключ на мютекс . Якщо взяти ключ до туалету (придбати замок), ви можете ним користуватися. Якщо ключа немає (замок заблокований), вам доведеться почекати. Коли особа поверне ключ ( відпустіть замок ), ви можете зараз придбати його.


Але приклад c # не підтримує підтвердження вашої черги, "передайте ключ наступній особі в черзі". Приклад - демонстрація стека або випадкових. 1, 2 і 3 всі запитують доступ у такій послідовності. Один спочатку пускають у охоронювану територію, а потім три. Черга дала б її другий.
donvnielsen

Я не мав на увазі жодної конкретної реалізації чи конкретної мови програмування. Мій приклад стосується високого рівня абстракції мютексу як принципу.
Чень А.

18

Щоб зрозуміти MUTEX, спочатку ви повинні знати, що таке "стан перегонів", а потім лише ви зрозумієте, для чого потрібен MUTEX. Припустимо, у вас є багатопотокова програма і у вас є дві нитки. Тепер у вас є одна робота в черзі. Перший потік перевірить чергу завдань, а після пошуку роботи він почне виконувати її. Другий потік також перевірить чергу завдань і виявить, що в черзі є одне завдання. Отже, він також призначить той же покажчик завдання. Отже, тепер, що відбувається, обидва потоки виконують одну і ту ж роботу. Це призведе до помилки сегментації. Це приклад стану гонки.

Рішення цієї проблеми - MUTEX. MUTEX - це вид замка, який замикає по одній нитці одночасно. Якщо інша нитка хоче її заблокувати, нитка просто блокується.

Тему MUTEX у цьому посиланні на файл PDF дійсно варто прочитати.


Під "темою MUTEX" ви мали на увазі розділ про семафори, адже його приклади є бінарними семафорами, правда?
Карл Г

2
ну а Mutex - це просто семафор зі значенням 1
marcoslhc

Як називається книга тієї глави, якою ви поділилися? Будь ласка
Омар Фароко Анік

@OmarFaroqueAnik, на яку посилається книга, - Розширене програмування Linux від CodeSourcery LLC, опубліковано New Riders Publishing та доступ до нього можна отримати з домашньої сторінки пов'язаного домену.
RMart

11

Mutexes корисні в ситуаціях, коли вам потрібно застосувати ексклюзивний доступ до ресурсу через декілька процесів, коли звичайний замок не допоможе, оскільки він працює лише через нитки.


Це справді правда? Немає окремих процесів створювати власну копію файлів?
Леон

0

Mutex: Mutex розшифровує поняття Mut ual Ex . Це означає, що один процес / потік може входити в критичний розділ. У паралельному програмуванні, де кілька потоків / процес намагається оновити спільний ресурс (будь-яка змінна, спільна пам'ять тощо) може призвести до несподіваного результату. (Оскільки результат залежить від того, який потік / процес отримує перший доступ).

Щоб уникнути такого несподіваного результату, нам потрібен механізм синхронізації, який гарантує, що лише один потік / процес отримує доступ до такого ресурсу одночасно.

Бібліотека 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

Це структура для типу даних mutex, тобто pthread_mutex_t. Коли mutex заблоковано, __lock встановлюється на 1. Коли він розблокований, __lock встановлюється на 0.

Це гарантує, що жоден два процеси / потоки не можуть отримати доступ до критичного розділу одночасно.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.