Коли ми повинні використовувати мутекс і коли слід використовувати семафор?
Коли ми повинні використовувати мутекс і коли слід використовувати семафор?
Відповіді:
Ось як я пам’ятаю, коли використовувати що -
Семафор: Використовуйте семафор, коли ви (нитка) хочете спати, поки якась інша нитка не скаже вам прокинутися. Семафор "Вниз" трапляється в одній нитці (виробник), а семафор "вгору" (для того ж семафору) трапляється в іншій потоці (споживач), наприклад: При проблемі виробник-споживач виробник хоче спати, поки щонайменше один буферний проріз не буде порожнім - лише споживча нитка може визначити, коли гніздо буфера порожнє
Mutex: Використовуйте mutex, коли ви (потік) хочете виконати код, який не повинен одночасно виконувати жоден інший потік. Mutex 'вниз' трапляється в одній нитці, а mutex 'вгору' повинен відбуватися в тій же ниті згодом. наприклад: Якщо ви видаляєте вузол із глобального пов'язаного списку, ви не хочете, щоб інший потік перебирався з покажчиками під час видалення вузла. Коли ви придбаєте мютекс і будете зайняті видаленням вузла, якщо інший потік намагається придбати той самий мютекс, він буде ввімкнений до сну, поки ви не відпустите файли.
Spinlock: використовуйте спінлок, коли ви дійсно хочете використовувати мютекс, але вашій нитці не дозволяється спати. наприклад: Обробник переривання в ядрі ОС ніколи не повинен спати. Якщо це зробити, система замерзне / вийде з ладу. Якщо вам потрібно вставити вузол у загальнодоступний зв’язаний список із обробника переривань, придбайте спінлок - вставити вузол - звільнити спінлок.
Мутекс - це об'єкт взаємного виключення, схожий на семафор, але який дозволяє одночасно лише один шаф, обмеження власності якого можуть бути більш суворими, ніж семафор.
Це можна вважати еквівалентним звичайному семафору лічильника (з підрахунком одиниці) і вимогою, щоб його можна було випустити лише тією самою ниткою, яка його зафіксувала (a) .
З іншого боку, семафор має довільну кількість і може бути заблокований цим шафками одночасно. І може не бути вимоги, щоб він був випущений тим самим потоком, на який він стверджував (але, якщо ні, ви повинні ретельно відстежувати, хто в даний момент несе відповідальність за нього, як і виділена пам'ять).
Отже, якщо у вас є декілька примірників ресурсу (скажімо, три стрічкові накопичувачі), ви можете використовувати семафор з кількістю 3. Зверніть увагу, що це не говорить вам, який із цих стрічкових накопичувачів у вас є, тільки що у вас є певна кількість.
Крім того, за допомогою семафорів можливе, що в одній шафці можна заблокувати кілька примірників ресурсу, наприклад, для копіювання стрічки на стрічку. Якщо у вас є один ресурс (скажімо місце пам’яті, яке ви не хочете пошкодити), мутекс більше підходить.
Еквівалентними операціями є:
Counting semaphore Mutual exclusion semaphore
-------------------------- --------------------------
Claim/decrease (P) Lock
Release/increase (V) Unlock
Убік: якщо ви коли-небудь замислювалися над химерними листами, які використовувались для претензій та звільнення семафорів, це тому, що винахідником був голландський. Зондник verlagen означає спробувати зменшити, а verhogen означає збільшити.
(а) ... або це можна розглядати як щось зовсім відмінне від семафору, що може бути безпечнішим з огляду на їх майже завжди різні види використання.
Дуже важливо розуміти, що мютекс - це не семафор з рахунком 1!
Це причина, що є такі речі, як бінарні семафори (це справді семафори з числом 1).
Різниця між Mutex і Binary-Semaphore полягає в принципі власності:
Мютекс набувається завданням, і тому він також повинен бути випущений тим самим завданням. Це дає змогу виправити декілька проблем із бінарними семафорами (Невиправданий випуск, рекурсивна тупикова ситуація та інверсія пріоритету).
Caveat: Я написав "робить можливим", якщо і як ці проблеми виправлені, залежить від реалізації ОС.
Оскільки мутекс повинен бути випущений тим самим завданням, це не дуже добре для синхронізації завдань. Але в поєднанні зі змінними стану ви отримуєте дуже потужні будівельні блоки для побудови всіх видів примітивів ipc.
Тому моя рекомендація: якщо у вас чітко реалізовані мутекси та змінні умови (наприклад, з pthreads POSIX), використовуйте їх.
Використовуйте семафори лише в тому випадку, якщо вони точно відповідають тій проблемі, яку ви намагаєтеся вирішити, не намагайтеся створювати інші примітиви (наприклад, rw-блокування з семафорів, використовуйте для них мютекси та змінні умови)
Існує багато нерозуміння мутексів і семафорів. Найкраще пояснення, яке я знайшов поки що, - у цій статті 3-ї частини:
Мутекс проти семафорів - Частина 1: Семафори
Мутекс проти Семафору - Частина 2: Мутекс
Mutex vs. Semaphores - Частина 3 (заключна частина): Проблеми взаємовиключення
Хоча відповідь @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 для подальших роз'яснень
sema_wait
:-) На мою думку, вони і щодо ресурсів, і повідомлення, що передається іншим потокам, є побічним ефектом (дуже важливим, продуктивним) захист.
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/… )
Див. "Приклад туалету" - http://pheatt.emporia.edu/courses/2010/cs557f10/hand07/Mutex%20vs_%20Semaphore.htm :
Mutex:
Є ключем до туалету. Один чоловік може мати ключ - займати туалет - у той час. Закінчивши, людина надає (звільняє) ключ наступній людині в черзі.
Офіційно: "Mutexes зазвичай використовуються для послідовного доступу до розділу коду повторного вступу, який не може бути виконаний одночасно більш ніж одним потоком. Об'єкт mutex дозволяє лише один потік в керований розділ, змушуючи інші потоки, які намагаються отримати доступ до цей розділ чекати, поки перший потік не вийде з цього розділу. " Ref: Бібліотека розробників Symbian
(Мутекс - це справді семафор зі значенням 1.)
Семафор:
Чи кількість безкоштовних однакових ключів для туалету. Наприклад, скажімо, у нас є чотири туалети з однаковими замками та ключами. Кількість семафорів - кількість клавіш - встановлюється на початку 4 (усі чотири туалети безкоштовні), тоді значення підрахунку зменшується по мірі заходу людей. Якщо всі туалети заповнені, тобто. не залишилося вільних клавіш, кількість семафорів дорівнює 0. Тепер, коли екв. одна людина виходить з туалету, семафор збільшується до 1 (один вільний ключ) і видається наступній людині в черзі.
Офіційно: "Семафор обмежує кількість одночасних користувачів спільного ресурсу до максимальної кількості. Нитки можуть запитувати доступ до ресурсу (декрементуючи семафор) і можуть сигналізувати про те, що вони закінчили використовувати ресурс (збільшуючи семафор). " Ref: Бібліотека розробників Symbian
Намагаюся не звучати задумливо, але не можу допомогти собі.
Ваше питання має полягати в тому, яка різниця між мютекс і семафорами? І якщо бути точнішим, питання має бути: "Який взаємозв'язок між мютекс і семафорами?"
(Я би додав це запитання, але я на сто відсотків впевнений, що якийсь надмірний модератор закриє його як дублікат, не розуміючи різниці між різницею та відносинами.)
В об’єктній термінології ми можемо зауважити, що:
спостереження.1 Семафор містить мутекс
спостереження.2 Mutex - не семафор, а семафор - не мутекс.
Є деякі семафори, які будуть діяти так, ніби вони - мютекс, які називаються бінарними семафорами, але вони відлякують НЕ мютекс.
Існує спеціальний інгредієнт під назвою Signaling (в позі використовується умовно-змінний для цього імені), необхідний для створення семафору з мютексу. Подумайте про це як про джерело сповіщень. Якщо два або більше потоків підписані на один і той же джерело сповіщень, тоді можна надіслати їм повідомлення в ОДНО або ВСІ, щоб прокинутися.
Може бути один чи більше лічильників, пов’язаних із семафорами, які охороняються мютексом. Найпростіший сценарій семафору, є один лічильник, який може бути або 0, або 1.
Ось тут плутається плутанина, як мусонний дощ.
Семафор із лічильником, який може бути 0 або 1, НЕ є мутексним файлом.
Mutex має два стани (0,1) та одне право власності (завдання). Семафор має мутекс, деякі лічильники та змінну стану.
Тепер використовуйте свою фантазію, і кожна комбінація використання лічильника та коли подавати сигнал може створити один вид семафору.
Одномісний лічильник зі значенням 0 або 1 і сигналізація, коли значення переходить на 1 І потім відмикає одного з хлопця, який чекає сигналу == Двійковий семафор
Єдиний лічильник зі значенням 0 до N та сигналізація, коли значення стає менше N, і блокує / чекає, коли значення дорівнює N == Підрахунок семафору
Єдиний лічильник зі значенням 0 до N та сигналізація, коли значення переходить до N, і блокує / чекає, коли значення менше N == Бар'єрний семафор (добре, якщо вони не називають його, тоді вони повинні.)
Тепер до вашого питання, коли використовувати що. (АБО скоріше правильна версія версії 3, коли використовувати мутекс та коли використовувати бінарний семафор, оскільки немає порівняння з небінарним семафором.) Використовуйте mutex, коли 1. ви хочете, щоб налаштована поведінка, яка не забезпечується бінарним семафорні, такі як спін-блокування або швидкісні або рекурсивні. Зазвичай ви можете налаштувати мутекси з атрибутами, але налаштування семафору - це не що інше, як написання нового семафору. 2. Ви хочете легкого АБО швидшого примітиву
Використовуйте семафори, коли саме те, що ви хочете, саме забезпечується.
Якщо ви не розумієте, що забезпечується вашою реалізацією бінарного семафору, то IMHO, використовуйте mutex.
І нарешті, читайте книгу, а не покладаючись лише на ТАК.
Я думаю, що питання має полягати в різниці між мютекс та бінарним семафором.
Mutex = Це механізм блокування власності, лише нитка, яка придбає замок, може звільнити замок.
binary Semaphore = Це більше механізм сигналу, будь-який інший потік вищого пріоритету, якщо хочете, може подати сигнал і зняти замок.
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. Ви можете сказати так, як це, але зауважте, що вони використовуються в різних випадках. Не замінюйте одне іншим, навіть якщо ви можете це зробити.
x = getx(); y = gety(); z = x + y;
За якою - то причини, ми використовуємо три нитки , щоб зробити три речі, тепер порядок потоків дуже важливо , тому що ми не можемо зробити , x + y
якщо getx
і gety
закінчили. Одним словом, семафор використовується, коли ми дбаємо про порядок виконання багаторізкових ниток.
x
і не y
будуть завершені, а потім обчисліть z = x + y
. Я знаю, що у Java є CyclicBarrier
. Крім того, я не впевнений, чи можу я сказати, що mapreduce
це також семафорний футляр, тому що я не можу, reduce
поки всі не map
будуть завершені.
Усі вищезазначені відповіді хорошої якості, але ця лише для запам'ятовування. Ім'я Mutex походить від Взаємно Ексклюзивного, отже, ви мотивовані думати про блокування mutex як Взаємовиключення між двома, як лише одним за одним, і якщо я Володіючи ним, ви можете мати його лише після того, як я відпущу його. З іншого боку, такого випадку не існує для Semaphore - це як сигнал трафіку (що також означає слово Semaphore).
Як було зазначено, семафор з числом одиниць - це те саме, що і «двійковий» семафор, який є тим же самим, що і мутекс.
Основне, що я бачив семафори, кількість яких перевищує кількість, яку використовували, - це ситуації виробників / споживачів, в яких у вас черга певного фіксованого розміру.
У вас тоді два семафори. Перший семафор спочатку встановлюється як кількість елементів у черзі, а другий семафор - 0. Виробник робить операцію P на першому семафорі, додає до черги. і робить операцію V на другу. Споживач робить операцію P на другому семафорі, видаляє з черги, а потім робить операцію V на першому.
Таким чином виробник блокується кожного разу, коли він заповнює чергу, а споживач блокується, коли черга порожня.
Мутекс - особливий випадок семафору. Семафор дозволяє декільком ниткам перейти в критичну секцію. Створюючи семафор, ви визначаєте, як можуть бути дозволені нитки в критичному розділі. Звичайно, ваш код повинен вміти обробляти кілька доступів до цього критичного розділу.
Бінарний семафор і Мутекс різні. З точки зору ОС, бінарний семафор і семафор рахування рахунків реалізовані однаково, і двійковий семафор може мати значення 0 або 1.
Mutex -> Може використовуватися лише для однієї і єдиної мети взаємного виключення для критичного розділу коду.
Семафор -> Може використовуватися для вирішення різноманітних проблем. Бінарний семафор може бути використаний для сигналізації, а також вирішити проблему взаємного виключення. При ініціалізації до 0 вона вирішує проблему сигналізації, а при ініціалізації на 1 - вирішує задачу взаємного виключення .
Коли кількість ресурсів більше і потребує синхронізації, ми можемо використовувати підрахунок семафору.
У своєму блозі я детально обговорив ці теми.
https://designpatterns-oo-cplusplus.blogspot.com/2015/07/synchronization-primitive-mutex-and.html