Коли ми повинні використовувати мутекс і коли слід використовувати семафор


Відповіді:


92

Ось як я пам’ятаю, коли використовувати що -

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

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

Spinlock: використовуйте спінлок, коли ви дійсно хочете використовувати мютекс, але вашій нитці не дозволяється спати. наприклад: Обробник переривання в ядрі ОС ніколи не повинен спати. Якщо це зробити, система замерзне / вийде з ладу. Якщо вам потрібно вставити вузол у загальнодоступний зв’язаний список із обробника переривань, придбайте спінлок - вставити вузол - звільнити спінлок.


1
додати до: семафори та мютекс - це два способи забезпечення синхронізації. семафор, може бути більше пов’язаний із сигналізацією (наприклад, сценарій проблеми виробника та споживача) та mutex, може бути більше пов'язаний із дозволом доступу до одного за раз (декілька запитів на доступ до спільного ресурсу, але лише один наданий одночасно). [приємна стаття: geeksforgeeks.org/mutex-vs-semaphore/]
парасити

57

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

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

З іншого боку, семафор має довільну кількість і може бути заблокований цим шафками одночасно. І може не бути вимоги, щоб він був випущений тим самим потоком, на який він стверджував (але, якщо ні, ви повинні ретельно відстежувати, хто в даний момент несе відповідальність за нього, як і виділена пам'ять).

Отже, якщо у вас є декілька примірників ресурсу (скажімо, три стрічкові накопичувачі), ви можете використовувати семафор з кількістю 3. Зверніть увагу, що це не говорить вам, який із цих стрічкових накопичувачів у вас є, тільки що у вас є певна кількість.

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

Еквівалентними операціями є:

Counting semaphore          Mutual exclusion semaphore
--------------------------  --------------------------
  Claim/decrease (P)                  Lock
  Release/increase (V)                Unlock

Убік: якщо ви коли-небудь замислювалися над химерними листами, які використовувались для претензій та звільнення семафорів, це тому, що винахідником був голландський. Зондник verlagen означає спробувати зменшити, а verhogen означає збільшити.


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


Гаразд, я також натрапив на бінарний семафор. Коли нам потрібно зайнятися бінарним семафором і коли нам слід використовувати мютекс?
Картик Балагуру

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

1
Інша потенційна відмінність реалізації - рекурсивна мютекс. Оскільки є лише один ресурс, одному потоку може бути дозволено його заблокувати кілька разів (доки він випускає його також у багато разів). З ресурсом з декількома примірниками це не так просто, оскільки ви, можливо, не знаєте, чи хоче нитка знову вимагати інший екземпляр або той самий екземпляр.
paxdiablo

1
Вони вирішують конкретну проблему. Той факт, що проблема, яку вони вирішують, - це люди, які не дуже виправляють мютекси, жодним чином не повинна принижувати рішення :-)
paxdiablo

5
Мутекс абсолютно відрізняється від двійкового семафору. Вибачте, але це визначення неправильне
Peer Stritzinger

49

Дуже важливо розуміти, що мютекс - це не семафор з рахунком 1!

Це причина, що є такі речі, як бінарні семафори (це справді семафори з числом 1).

Різниця між Mutex і Binary-Semaphore полягає в принципі власності:

Мютекс набувається завданням, і тому він також повинен бути випущений тим самим завданням. Це дає змогу виправити декілька проблем із бінарними семафорами (Невиправданий випуск, рекурсивна тупикова ситуація та інверсія пріоритету).

Caveat: Я написав "робить можливим", якщо і як ці проблеми виправлені, залежить від реалізації ОС.

Оскільки мутекс повинен бути випущений тим самим завданням, це не дуже добре для синхронізації завдань. Але в поєднанні зі змінними стану ви отримуєте дуже потужні будівельні блоки для побудови всіх видів примітивів ipc.

Тому моя рекомендація: якщо у вас чітко реалізовані мутекси та змінні умови (наприклад, з pthreads POSIX), використовуйте їх.

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

Існує багато нерозуміння мутексів і семафорів. Найкраще пояснення, яке я знайшов поки що, - у цій статті 3-ї частини:

Мутекс проти семафорів - Частина 1: Семафори

Мутекс проти Семафору - Частина 2: Мутекс

Mutex vs. Semaphores - Частина 3 (заключна частина): Проблеми взаємовиключення


URL-адреси цього веб-сайту містять прикольні символи, тому вони не працюють ... Я працюю над цим
Peer Stritzinger

13

Хоча відповідь @opaxdiablo абсолютно правильна, я хотів би зазначити, що сценарій використання обох речей зовсім інший. Мутекс використовується для захисту частин коду від одночасного запуску, семафори використовуються для одного потоку для передачі сигналу іншому потоку для запуску.

/* Task 1 */
pthread_mutex_lock(mutex_thing);
    // Safely use shared resource
pthread_mutex_unlock(mutex_thing);



/* Task 2 */
pthread_mutex_lock(mutex_thing);
   // Safely use shared resource
pthread_mutex_unlock(mutex_thing); // unlock mutex

Сценарій семафору інший:

/* Task 1 - Producer */
sema_post(&sem);   // Send the signal

/* Task 2 - Consumer */
sema_wait(&sem);   // Wait for signal

Див. Http://www.netrino.com/node/202 для подальших роз'яснень


2
Ти маєш рацію. Навіть якщо ви використовуєте семафор з кількістю одиниць, ви маєте на увазі щось, що ви робите, ніж якщо б ви використовували мютекс.
всезначний

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

You say that the usage pattern of semaphores is to notify threadsОдин пункт про сповіщення потоків. Можна зателефонуватиsem_post безпечно від обробника сигналів ( pubs.opengroup.org/onlinepubs/009695399/functions/… ), але не рекомендувати дзвінки pthread_mutex_lockта pthread_mutex_unlockвід обробників сигналів ( manpages.ubuntu.com/manpages/lucid/man3/… )

@paxdiablo: Є одна основна відмінність цього мутексного бінарного семафору - це підтримка кількості відліку. Mutex або, можна сказати, будь-який умовний mutex не підтримує жодного рахунку, пов’язаного з блокуванням, де в якості sempahore використовують для підтримки кількості. Тож sem_wait і sem_post підтримують кількість.
Prak

9

Див. "Приклад туалету" - http://pheatt.emporia.edu/courses/2010/cs557f10/hand07/Mutex%20vs_%20Semaphore.htm :

Mutex:

Є ключем до туалету. Один чоловік може мати ключ - займати туалет - у той час. Закінчивши, людина надає (звільняє) ключ наступній людині в черзі.

Офіційно: "Mutexes зазвичай використовуються для послідовного доступу до розділу коду повторного вступу, який не може бути виконаний одночасно більш ніж одним потоком. Об'єкт mutex дозволяє лише один потік в керований розділ, змушуючи інші потоки, які намагаються отримати доступ до цей розділ чекати, поки перший потік не вийде з цього розділу. " Ref: Бібліотека розробників Symbian

(Мутекс - це справді семафор зі значенням 1.)

Семафор:

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

Офіційно: "Семафор обмежує кількість одночасних користувачів спільного ресурсу до максимальної кількості. Нитки можуть запитувати доступ до ресурсу (декрементуючи семафор) і можуть сигналізувати про те, що вони закінчили використовувати ресурс (збільшуючи семафор). " Ref: Бібліотека розробників Symbian


7

Намагаюся не звучати задумливо, але не можу допомогти собі.

Ваше питання має полягати в тому, яка різниця між мютекс і семафорами? І якщо бути точнішим, питання має бути: "Який взаємозв'язок між мютекс і семафорами?"

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

В об’єктній термінології ми можемо зауважити, що:

спостереження.1 Семафор містить мутекс

спостереження.2 Mutex - не семафор, а семафор - не мутекс.

Є деякі семафори, які будуть діяти так, ніби вони - мютекс, які називаються бінарними семафорами, але вони відлякують НЕ мютекс.

Існує спеціальний інгредієнт під назвою Signaling (в позі використовується умовно-змінний для цього імені), необхідний для створення семафору з мютексу. Подумайте про це як про джерело сповіщень. Якщо два або більше потоків підписані на один і той же джерело сповіщень, тоді можна надіслати їм повідомлення в ОДНО або ВСІ, щоб прокинутися.

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

Ось тут плутається плутанина, як мусонний дощ.

Семафор із лічильником, який може бути 0 або 1, НЕ є мутексним файлом.

Mutex має два стани (0,1) та одне право власності (завдання). Семафор має мутекс, деякі лічильники та змінну стану.

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

  1. Одномісний лічильник зі значенням 0 або 1 і сигналізація, коли значення переходить на 1 І потім відмикає одного з хлопця, який чекає сигналу == Двійковий семафор

  2. Єдиний лічильник зі значенням 0 до N та сигналізація, коли значення стає менше N, і блокує / чекає, коли значення дорівнює N == Підрахунок семафору

  3. Єдиний лічильник зі значенням 0 до N та сигналізація, коли значення переходить до N, і блокує / чекає, коли значення менше N == Бар'єрний семафор (добре, якщо вони не називають його, тоді вони повинні.)

Тепер до вашого питання, коли використовувати що. (АБО скоріше правильна версія версії 3, коли використовувати мутекс та коли використовувати бінарний семафор, оскільки немає порівняння з небінарним семафором.) Використовуйте mutex, коли 1. ви хочете, щоб налаштована поведінка, яка не забезпечується бінарним семафорні, такі як спін-блокування або швидкісні або рекурсивні. Зазвичай ви можете налаштувати мутекси з атрибутами, але налаштування семафору - це не що інше, як написання нового семафору. 2. Ви хочете легкого АБО швидшого примітиву

Використовуйте семафори, коли саме те, що ви хочете, саме забезпечується.

Якщо ви не розумієте, що забезпечується вашою реалізацією бінарного семафору, то IMHO, використовуйте mutex.

І нарешті, читайте книгу, а не покладаючись лише на ТАК.


5

Я думаю, що питання має полягати в різниці між мютекс та бінарним семафором.

Mutex = Це механізм блокування власності, лише нитка, яка придбає замок, може звільнити замок.

binary Semaphore = Це більше механізм сигналу, будь-який інший потік вищого пріоритету, якщо хочете, може подати сигнал і зняти замок.


5

Mutex - це захист спільного ресурсу.
Семафор - це відправлення ниток.

Mutex:
Уявіть, що на продаж є кілька квитків. Ми можемо імітувати випадок, коли багато людей купують квитки одночасно: кожна людина є ниткою для придбання квитків. Очевидно, що нам потрібно використовувати мютекс для захисту квитків, оскільки це спільний ресурс.


Семафор:
Уявіть, що нам потрібно зробити розрахунок, як показано нижче:

c = a + b;

Також нам потрібна функція geta()для обчислення a, функція getb()для обчислення bі функція getc()для обчислення c = a + b.

Очевидно, що ми не можемо зробити, c = a + bякщо не буде geta()і getb()не закінчено.
Якщо три функції - це три потоки, нам потрібно відправити три потоки.

int a, b, c;
void geta()
{
    a = calculatea();
    semaphore_increase();
}

void getb()
{
    b = calculateb();
    semaphore_increase();
}

void getc()
{
    semaphore_decrease();
    semaphore_decrease();
    c = a + b;
}

t1 = thread_create(geta);
t2 = thread_create(getb);
t3 = thread_create(getc);
thread_join(t3);

За допомогою семафору наведений вище код може переконатися, що t3він не зробить свою роботу досі t1і t2зробив свою роботу.

Словом, семафор - це змусити нитки виконуватись як логічне замовлення, тоді як mutex - захист спільного ресурсу.
Тому вони НЕ одне і те ж, навіть якщо деякі люди завжди кажуть, що мютекс - це особливий семафор з початковим значенням 1. Ви можете сказати так, як це, але зауважте, що вони використовуються в різних випадках. Не замінюйте одне іншим, навіть якщо ви можете це зробити.


Продаж квитків є акуратним прикладом. Приклад семафору трохи незрозумілий (для мене все одно).
prayagupd

1
Приклад "Семафор" @prayagupd - зробити нитки в певному порядку, тоді як продаж квитків не потребує жодного замовлення. Якщо є три людини: a, b і c. Коли вони приходять купувати квитки, нас взагалі не хвилює порядок придбання квитків. Однак, якщо ми робимо такий розрахунок: x = getx(); y = gety(); z = x + y;За якою - то причини, ми використовуємо три нитки , щоб зробити три речі, тепер порядок потоків дуже важливо , тому що ми не можемо зробити , x + yякщо getxі getyзакінчили. Одним словом, семафор використовується, коли ми дбаємо про порядок виконання багаторізкових ниток.
Ів

дістався ти. Це звучить схоже на бар’єр . Я можу сказати, що зачекайте, поки нитки xі не yбудуть завершені, а потім обчисліть z = x + y. Я знаю, що у Java є CyclicBarrier. Крім того, я не впевнений, чи можу я сказати, що mapreduceце також семафорний футляр, тому що я не можу, reduceпоки всі не mapбудуть завершені.
prayagupd

@prayagupd Так. Ви можете сказати це.
Ів

2

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


1

Як було зазначено, семафор з числом одиниць - це те саме, що і «двійковий» семафор, який є тим же самим, що і мутекс.

Основне, що я бачив семафори, кількість яких перевищує кількість, яку використовували, - це ситуації виробників / споживачів, в яких у вас черга певного фіксованого розміру.

У вас тоді два семафори. Перший семафор спочатку встановлюється як кількість елементів у черзі, а другий семафор - 0. Виробник робить операцію P на першому семафорі, додає до черги. і робить операцію V на другу. Споживач робить операцію P на другому семафорі, видаляє з черги, а потім робить операцію V на першому.

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


1

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


-1

Бінарний семафор і Мутекс різні. З точки зору ОС, бінарний семафор і семафор рахування рахунків реалізовані однаково, і двійковий семафор може мати значення 0 або 1.

Mutex -> Може використовуватися лише для однієї і єдиної мети взаємного виключення для критичного розділу коду.

Семафор -> Може використовуватися для вирішення різноманітних проблем. Бінарний семафор може бути використаний для сигналізації, а також вирішити проблему взаємного виключення. При ініціалізації до 0 вона вирішує проблему сигналізації, а при ініціалізації на 1 - вирішує задачу взаємного виключення .

Коли кількість ресурсів більше і потребує синхронізації, ми можемо використовувати підрахунок семафору.

У своєму блозі я детально обговорив ці теми.

https://designpatterns-oo-cplusplus.blogspot.com/2015/07/synchronization-primitive-mutex-and.html

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