Різниця між бінарним семафором і м ятею


819

Чи є різниця між бінарним семафором і мютекс або вони по суті однакові?


11
Вони семантично однакові, але на практиці ви помітите дивні відмінності (особливо в Windows).
Майкл Фукаракіс

5
@Michael Foukarakis: Які дивні відмінності?
Філіпп

2
Я гадаю, дивним був не правильний вираз. Мутекс також підтримує право власності та іноді повторне введення. Це справа в Windows. Крім того, семафори в Windows реалізовані поверх об’єктів Event, проте я не впевнений у практичних наслідках цього.
Майкл Фукаракіс,

1
Подібна дискусія в stackoverflow.com/questions/4039899/…
Karthik Balaguru

2
@philipxy Добре сховав 'rn' замість 'm'.
Mooncrater

Відповіді:


691

Вони НЕ одне і те ж. Вони використовуються для різних цілей!
Хоча обидва типи семафорів мають повний / порожній стан і використовують один і той же API, їх використання дуже відрізняється.

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

Семафор Mutex "належить" завданню, яке його бере. Якщо Завдання B намагається передати semtex в мютекс, який зараз знаходиться у завданні A, виклик завдання B поверне помилку та не вдасться.

Mutexes завжди використовує таку послідовність:

  - SemTake
  - Критичний розділ
  - SemGive

Ось простий приклад:

  Нитка A Нитка B
   Візьміть Мутекс
     доступ до даних
     ... Візьміть Mutex <== Заблокуємо
     ...
   Надати Mutex дані доступу <== Розблокувати
                                  ...
                                Дайте Мутекс

Бінарний семафор
Бінарний семафор стосується зовсім іншого питання:

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

   Task A                      Task B
   ...                         Take BinSemaphore   <== wait for something
   Do Something Noteworthy
   Give BinSemaphore           do something    <== unblocks

Зауважте, що з двійковим семафором нормально B взяти семафор, а A - надати його.
Знову ж таки, двійковий семафор НЕ захищає ресурс від доступу. Акт дарування та взяття семафору принципово відокремлений.
Зазвичай це мало сенсу для одного і того ж завдання, щоб дати подачу і взяти на себе той же бінарний семафор.


12
Хіба це мутекс не кращий, ніж двійковий семафор? Оскільки це не має сенсу, якщо хтось випускає замок, якого він насправді не тримає.
Pacerier

111
Вони мають різні цілі. Mutex призначений для ексклюзивного доступу до ресурсу. Для синхронізації слід використовувати двійковий семафор (тобто "Ей, хтось! Це сталося!"). Бінарний "дарувальник" просто повідомляє того, хто "приймав", що те, чого вони чекали, сталося.
Бенуа

5
@Pacerier Ви плутаєте мету. Мутекс призначений для захисту критичної області. Ви маєте рацію, що не має сенсу використовувати двійковий семафор. Я оновлю відповідь, щоб пояснити мету кожного.
Бенуа

4
@ Benoit Отже, чи можна сказати, що Mutex використовується для атомності, а Бінарний Семафор для перспективи впорядкування, оскільки Завдання B буде чекати завдання A, щоб сповістити про звільнення блокування, переконавшись в упорядкуванні операцій над структурою даних?
abhi

1
@abhi Це хороший спосіб подивитися на Mutex. Однак, залежно від ОС, у вас може бути більше одного одержувача, який чекає на бінарний семафор. У такому випадку лише один клієнт отримає двійкове число. Інші (і) чекатимуть наступного. Чи відомий або гарантований порядок отримання? Залежить від ОС.
Бенуа

446
  • М'ютекс може бути звільнений тільки потік , який придбав його .
  • Бінарний семафор може бути переданий будь-яким потоком (або процесу).

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

У Windows бінарні семафори більше схожі на предмети події, ніж на мутекси.


34
Mutex can be released only by thread that had acquired it- Я щойно спробував за допомогою простої програми на основі pthread_mutex, потік може розблокувати mutex, заблокований у головній темі
Дейзі

15
@ warl0ck Згідно з довідковою сторінкою pthread_mutex_lock linux.die.net/man/3/pthread_mutex_lock : "Якщо тип mutex - PTHREAD_MUTEX_ERRORCHECK, то перевірка помилок буде надана .... Якщо потік намагається розблокувати мутекс, який у нього є не заблокований або мютекс, який розблокований, помилка повертається. "
квітня 13

47
@ Warl0ck ласка , дивіться stackoverflow.com/a/5492499/385064 «Pthreads має 3 різних видів м'ютексів: Швидкий м'ютекс, рекурсивний м'ютекс і перевірка помилок м'ютекс. Ви використовували швидкий mutex, який з міркувань продуктивності не перевіряє на цю помилку. Якщо ви скористаєтеся помилкою перевірки mutex в Linux, ви отримаєте очікувані результати. "
FrostNovaZzz

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

1
@achoora Я погоджуюся, що неправильно спеціалізувати семафор для синхронізації. Насправді всі мутекс, бінарний семафор, бар'єр, трубопроводи - це різні схеми синхронізації. У перспективі дизайну mutex більше схожий на зразок стану, де алгоритм, який обраний державою, може змінити стан. Бінарний семафор більше схожий на шаблон стратегії, коли зовнішній алгоритм може змінювати стан і, зрештою, алгоритм / стратегію, обрану для запуску.
шува

442

Приклад туалету - це приємна аналогія:

Mutex:

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

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

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

Семафор:

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

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


234
... але це стосується мутексу проти підрахунку семафору. Було задано питання про бінарне.
Роман Нікітченко

24
Хоча те, що сказав Давид, є правильним, але НЕ є відповіддю на поставлене питання. Відповідь Младена Янковича - це відповідь на поставлене запитання, де робиться точка диференціації "бінарний семафор" проти "мутекс".
Ajeet Ganga

13
На жаль, ця неправильна відповідь має більше голосів, ніж найкраща відповідь @Benoit
NeonGlow

6
Ця відповідь вводить в оману. Їх слід було порівняти лише з Бінарним Семафором.
Гемант

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

151

Приємні статті на тему:

З частини 2:

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


Дякую за посилання, пояснення там чудові. Посилання змінилося: feabhas.com/blog/2009/09/… (Використовуйте <Попередня та Наступна> для переходу до інших двох статей.
Аарон Х.

@Aaron Я поправив посилання
суддя Мейґарден

Примітка - відсутність права власності також заважає операційній системі обійти пріоритетну інверсію. З цієї причини я, як правило, використовую змінні умови на відміну від семафорів для архітектур виробника / споживача.
kgriffs

1
+1 чудовий посилання на статтю Найкраща стаття, що пояснює семафор і мютекс за допомогою computing.llnl.gov/tutorials/pthreads, що пояснювала семафор і мютекс, я використав цю статтю як посилання на сцену, яка технічно все пояснює mutex / conditionals та інші конструкції, побудовані на їх вершині, як семафор / бар’єр / читач-письменник, але ніде не мають чітких та стислих проблем, з якими стикаються конструкції. Коротше кажучи, це посилання. :)
Ajeet Ganga

легше зрозуміти, ніж інші відповіді.
BinaryTreeee

101

Оскільки жоден з вищезазначених відповідей не усуває плутанину, ось такий, який очистив мою плутанину.

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

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

Джерело: http://www.geeksforgeeks.org/mutex-vs-semaphore/


42

Їх семантика синхронізації сильно відрізняється:

  • mutexes дозволяють серіалізувати доступ до заданого ресурсу, тобто кілька потоків чекають блокування, по одному, і, як було сказано раніше, потік володіє замком, поки це не буде зроблено: тільки цей конкретний потік може розблокувати його.
  • двійковий семафор - це лічильник зі значеннями 0 і 1: завдання, що блокує його, поки будь-яке завдання не зробить напівпост. Семафор рекламує, що ресурс є, і він забезпечує механізм дочекатися, поки йому буде сигналізовано як про доступність.

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


23

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

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

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

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

Count down from 5000:
     i. Execute the test-and-set instruction
    ii. If the mutex is clear, we have acquired it in the previous instruction 
        so we can exit the loop
   iii. When we get to zero, give up our time slice.

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

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

Основний алгоритм семафору виглядає так:

(somewhere in the program startup)
Initialise the semaphore to its start-up value.

Acquiring a semaphore
   i. (synchronised) Attempt to decrement the semaphore value
  ii. If the value would be less than zero, put the task on the tail of the list of tasks waiting on the semaphore and give up the time slice.

Posting a semaphore
   i. (synchronised) Increment the semaphore value
  ii. If the value is greater or equal to the amount requested in the post at the front of the queue, take that task off the queue and make it runnable.  
 iii. Repeat (ii) for all tasks until the posted value is exhausted or there are no more tasks waiting.

У випадку двійкового семафору основною практичною відмінністю між ними є характер системних служб, що оточують фактичну структуру даних.

РЕДАКТУВАННЯ: Як справедливо зазначав Еван, спіллокс сповільнить роботу однієї процесорної машини. Ви б використовували спінлок на мультипроцесорній коробці, оскільки на одному процесорі процес, що містить мутекс, ніколи не скине його під час виконання іншого завдання. Спінлок корисний лише для багатопроцесорних архітектур.


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

Зазвичай ви використовуєте спінкі лише в багатопроцесорних системах.
СтурбованоOfTunbridgeWells

Навіть на SMP після декількох обертів ви повертаєтесь до режиму сну / пробудження, що підтримується ОС. (наприклад, futexсистемний виклик Linux існує для сприяння реалізації файлів mutex / semaphore з низькою затримкою. en.wikipedia.org/wiki/Futex ) На швидкому шляху без суперечок або якщо ресурс стане доступним незабаром, ви ніколи не матимете накладних витрат системний виклик. Але ви не витрачаєте більше декількох мікросекунд, зайнятих в очікуванні (прядіння). Налаштування параметрів відключення та очікування залежить, звичайно, від апаратного та навантаження, але стандартна бібліотека, як правило, має розумний вибір.
Пітер Кордес

19

Хоча mutex і семафори використовуються як примітиви синхронізації, між ними існує велика різниця. Що стосується мутексу, розблокувати його може лише нитка, яка заблокувала або придбала мютекс. У випадку семафору нитка, що чекає на семафорі, може сигналізуватися іншою ниткою. Деякі операційні системи підтримують використання мутексу та семафорів між процесом. Зазвичай використання створюється у спільній пам'яті.


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

15

Mutex: Припустимо, у нас є критична нитка розділу T1, яка хоче отримати доступ до неї, після чого слід нижче. T1:

  1. Блокування
  2. Використовуйте критичний розділ
  3. Розблокувати

Бінарний семафор: Він працює на основі сигналу очікування та сигналу. очікування (і) зменшення значення "s" на одне зазвичай значення "s" ініціалізується зі значенням "1", сигнал (и) збільшує значення "s" на одиницю. якщо значення "s" дорівнює 1 означає, що ніхто не використовує критичний розділ, коли значення 0 означає, що критичний розділ використовується. припустимо, що нитка Т2 використовує критичний переріз, тоді це слід нижче. T2:

  1. wait (s) // спочатку s значення є одним після виклику wait, його значення зменшилося на один, тобто 0
  2. Використовуйте критичний розділ
  3. сигнал (и) // тепер значення s збільшується і стає 1

Основна відмінність між Mutex і Бінарним семафором полягає в Mutext, якщо нитка блокує критичну секцію, тоді вона має розблокувати критичну секцію, жодна інша нитка не може її розблокувати, але у випадку бінарного семафору, якщо одна нитка блокує критичну секцію за допомогою функції очікування (s), тоді значення з s стають "0", і ніхто не може отримати доступ до нього, поки значення "s" не стане 1, але припустимо, що деякий інший сигнал виклику потоку тоді значення "s" стає 1, і це дозволяє іншій функції використовувати критичну секцію. отже, у бінарному семафорному потоці немає права власності.


12

У Windows є дві відмінності між мютексами та бінарними семафорами:

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

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


4
Хороша відповідь. У №2 ви описуєте рекурсивний мютекс - не всі мутекси обов'язково рекурсивні. Наприклад, cs.wustl.edu/~schmidt/ACE.FAQ.html#Q14
Dan

10

Ви, очевидно, використовуєте mutex для блокування даних в одному потоці, отримуючи доступ до іншого потоку одночасно. Припустимо, що ви щойно зателефонували lock()та отримуєте доступ до даних. Це означає, що ви не очікуєте, що будь-який інший потік (або інший екземпляр того ж коду потоку) отримає доступ до тих самих даних, заблокованих тим самим мутекс. Тобто, якщо це той самий потік-код, який виконується на іншому екземплярі потоку, потрапляє в замок, тоlock()має перекрити там контрольний потік. Це стосується потоку, який використовує інший потіковий код, який також отримує доступ до тих самих даних і який також блокується тим самим мютекс. У цьому випадку ви все ще перебуваєте в процесі доступу до даних, і ви можете зайняти, скажімо, ще 15 секунд, щоб дістатися до розблокування файлу mutex (щоб другий потік, який заблокується в блокуванні mutex, розблокував і дозволив керувати доступ до даних). Чи дозволите ви будь-якою ціною дозволити ще одному потоку просто розблокувати той самий мютекс, а ви, в свою чергу, дозволити потоці, яка вже чекає (блокується) в блоці mutex, розблокувати та отримати доступ до даних? Сподіваюся, ви отримали те, що я тут говорю? Відповідно до загального визначення !,

  • з "mutex" цього не може статися. Жодна інша нитка не може розблокувати замок у вашій нитці
  • з «бінарним семафором» це може статися. Будь-яка інша нитка може розблокувати замок у вашій нитці

Отже, якщо ви дуже конкретно ставитесь до використання бінарного семафору замість мютексу, то вам слід бути дуже обережним у “обстеженні” замків та розблокувань. Я маю на увазі, що кожен потік управління, який потрапляє на кожен замок, повинен потрапляти на виклик розблокування, також не повинно бути "першого розблокування", скоріше він повинен бути "першим блокуванням".


10

Mutex використовуються для "Замикаючих механізмів". один процес за один раз може використовувати спільний ресурс

тоді як

Семафори використовуються для "Механізмів сигналізації" на кшталт "Я закінчив, тепер можна продовжувати"


9

Міф:

Пара статей говорить про те, що "бінарний семафор і мютекс однакові" або "Семафор зі значенням 1 є мутекс", але основна відмінність полягає в тому, що Mutex може бути випущений лише потоком, який його придбав, тоді як ви можете сигналізувати семафору з будь-якого іншого потоку

Ключові моменти:

• Нитка може придбати більше одного замка (Mutex).

• Мютекс може бути заблокований не раз, лише якщо його рекурсивна мютекс, тут і блокування, і розблокування для мютексу повинні бути однаковими

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

• Бінарний семафор і мютекс схожі, але не однакові.

• Mutex - це затратна експлуатація завдяки пов'язаним з нею протоколам захисту.

• Основна мета mutex - досягнення атомного доступу або блокування ресурсу


8

Мьютекса контролює доступ до одного спільного ресурсу. Він надає операції з отримання () доступу до цього ресурсу та випуску (), коли це зроблено.

Семафор управляє доступом до загального пулу ресурсів. Він надає операції Wait (), поки не стане доступним один із ресурсів у пулі, і Signal (), коли він повернеться до пулу.

Коли кількість ресурсів, які захищає Семафор, перевищує 1, це називається лічильним семафором . Коли він керує одним ресурсом, його називають булевим семафором . Булевий семафор еквівалентний мутексу.

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


6

Модифіковане запитання - в чому різниця між мютекс та "бінарним" семафором у "Linux"?

Відповідь: Нижче наведені відмінності - i) Сфера застосування - Область застосування мютексу знаходиться в просторі адресного процесу, який створив її, і використовується для синхронізації потоків. Тоді як семафор може використовуватися в просторі процесу, а значить, він може використовуватися для міжпроцесорної синхронізації.

ii) Мутекс легший і швидший, ніж семафор. Футекс ще швидше.

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


і) Неправильно. ii) Джерело? iii) Це залежить.
curiousguy

6

Різниця між Бінарним Семафором та Мутексом: ВЛАСНІСТЬ: Семафори можуть сигналізуватися (розміщуватися) навіть від поточного власника. Це означає, що ви можете просто розмістити повідомлення з будь-якої іншої теми, хоча ви не є власником.

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


5

Mutex працює над блокуванням критичної області, але Semaphore працює на рахунку.


5

http://www.geeksforgeeks.org/archives/9102 детально обговорює.

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

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


4

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


У яких конкретних випадках гарантується справедливість для семафорів, а не для мутексів?
curiousguy

1
POSIX має специфічні вимоги, потік повинен бути розбуджений sem_post()для SCHED_FIFOі SCHED_RR(обидва з них не по замовчуванням): найвищий пріоритет потоку, і , якщо є кілька з тим же пріоритетом, нитки , які довго чекали довше. OpenSolaris певною мірою дотримується цього правила FIFO навіть для звичайного планування. Для glibc та FreeBSD розблокування простого мютексу (тобто не пріоритетного захисту чи пріоритетного успадкування) та розміщення семафору в основному однакові, позначаючи об'єкт як розблокований, а потім, якщо можуть бути потоки очікування, закликаючи ядро ​​прокинути його.
jilles

4

У вікнах різниця вказана нижче. MUTEX: процес, який успішно виконує очікування , повинен виконати сигнал і навпаки. БІНАРНІ СЕМАФОРИ: Різні процеси можуть виконувати операцію очікування або сигналу на семафорі.


4

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

  • Випадкове звільнення
  • Рекурсивний тупик
  • Завдання Смертний тупик

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

наприклад, ви можете увімкнути атрибут перевірки помилок у вашому файлі mutex. Помилка перевірки файлів mutexes повертається, EDEADLKякщо ви спробуєте заблокувати той самий двічі та EPERMякщо ви розблокуєте мутекс, який не є вашим.

pthread_mutex_t mutex;
pthread_mutexattr_t attr;
pthread_mutexattr_init (&attr);
pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_ERRORCHECK_NP);
pthread_mutex_init (&mutex, &attr);

Після ініціалізації ми можемо помістити ці чеки в наш код так:

if(pthread_mutex_unlock(&mutex)==EPERM)
 printf("Unlock failed:Mutex not owned by this thread\n");

4

Концепція була зрозумілою мені після переходу вище посад. Але були деякі затяжні питання. Отже, я написав цей невеликий фрагмент коду.

Коли ми намагаємось дати семафор, не приймаючи його, він проходить. Але, коли ви намагаєтесь надати мютекс, не беручи його, він не вдається. Я тестував це на платформі Windows. Увімкніть USE_MUTEX для запуску одного і того ж коду за допомогою MUTEX.

#include <stdio.h>
#include <windows.h>
#define xUSE_MUTEX 1
#define MAX_SEM_COUNT 1

DWORD WINAPI Thread_no_1( LPVOID lpParam );
DWORD WINAPI Thread_no_2( LPVOID lpParam );

HANDLE Handle_Of_Thread_1 = 0;
HANDLE Handle_Of_Thread_2 = 0;
int Data_Of_Thread_1 = 1;
int Data_Of_Thread_2 = 2;
HANDLE ghMutex = NULL;
HANDLE ghSemaphore = NULL;


int main(void)
{

#ifdef USE_MUTEX
    ghMutex = CreateMutex( NULL, FALSE, NULL);
    if (ghMutex  == NULL) 
    {
        printf("CreateMutex error: %d\n", GetLastError());
        return 1;
    }
#else
    // Create a semaphore with initial and max counts of MAX_SEM_COUNT
    ghSemaphore = CreateSemaphore(NULL,MAX_SEM_COUNT,MAX_SEM_COUNT,NULL);
    if (ghSemaphore == NULL) 
    {
        printf("CreateSemaphore error: %d\n", GetLastError());
        return 1;
    }
#endif
    // Create thread 1.
    Handle_Of_Thread_1 = CreateThread( NULL, 0,Thread_no_1, &Data_Of_Thread_1, 0, NULL);  
    if ( Handle_Of_Thread_1 == NULL)
    {
        printf("Create first thread problem \n");
        return 1;
    }

    /* sleep for 5 seconds **/
    Sleep(5 * 1000);

    /*Create thread 2 */
    Handle_Of_Thread_2 = CreateThread( NULL, 0,Thread_no_2, &Data_Of_Thread_2, 0, NULL);  
    if ( Handle_Of_Thread_2 == NULL)
    {
        printf("Create second thread problem \n");
        return 1;
    }

    // Sleep for 20 seconds
    Sleep(20 * 1000);

    printf("Out of the program \n");
    return 0;
}


int my_critical_section_code(HANDLE thread_handle)
{

#ifdef USE_MUTEX
    if(thread_handle == Handle_Of_Thread_1)
    {
        /* get the lock */
        WaitForSingleObject(ghMutex, INFINITE);
        printf("Thread 1 holding the mutex \n");
    }
#else
    /* get the semaphore */
    if(thread_handle == Handle_Of_Thread_1)
    {
        WaitForSingleObject(ghSemaphore, INFINITE);
        printf("Thread 1 holding semaphore \n");
    }
#endif

    if(thread_handle == Handle_Of_Thread_1)
    {
        /* sleep for 10 seconds */
        Sleep(10 * 1000);
#ifdef USE_MUTEX
        printf("Thread 1 about to release mutex \n");
#else
        printf("Thread 1 about to release semaphore \n");
#endif
    }
    else
    {
        /* sleep for 3 secconds */
        Sleep(3 * 1000);
    }

#ifdef USE_MUTEX
    /* release the lock*/
    if(!ReleaseMutex(ghMutex))
    {
        printf("Release Mutex error in thread %d: error # %d\n", (thread_handle == Handle_Of_Thread_1 ? 1:2),GetLastError());
    }
#else
    if (!ReleaseSemaphore(ghSemaphore,1,NULL) )      
    {
        printf("ReleaseSemaphore error in thread %d: error # %d\n",(thread_handle == Handle_Of_Thread_1 ? 1:2), GetLastError());
    }
#endif

    return 0;
}

DWORD WINAPI Thread_no_1( LPVOID lpParam ) 
{ 
    my_critical_section_code(Handle_Of_Thread_1);
    return 0;
}


DWORD WINAPI Thread_no_2( LPVOID lpParam ) 
{
    my_critical_section_code(Handle_Of_Thread_2);
    return 0;
}

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


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

2

Mutex використовується для захисту чутливого коду та даних, семафор використовується для синхронізації. Ви також можете практично використовувати захист чутливого коду, але може виникнути ризик звільнення захисту іншим потоком операцією V.So Основна Різниця між бісемафором і мютекс - це право власності. Наприклад, туалет, Mutex такий, що можна входити до туалету і зачиняти двері, ніхто більше не може входити, поки чоловік не вийде, бісемафор - це такий, як можна ввійти. туалет і замкнути двері, але хтось інший міг би увійти, попросивши адміністратора відкрити двері, це смішно.


2

Мутекс

Mutexes зазвичай використовуються для послідовного доступу до розділу коду повторного вступу, який не може бути виконаний одночасно більш ніж одним потоком. Об'єкт mutex дозволяє лише один потік в контрольованому розділі, змушуючи інші потоки, які намагаються отримати доступ до цього розділу, чекати, поки перший потік не вийде з цього розділу. Попереднє використання mutex для захисту спільного ресурсу може становити небезпеку ненавмисний побічний ефект. Будь-які два завдання RTOS, які працюють з різними пріоритетами та координуються через мьютекс, створюють можливість для інверсії пріоритетів . Mutex працює в просторі користувача .

Семафор

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


1

Відповідь може залежати від цільової ОС. Наприклад, щонайменше одна реалізація RTOS, з якою я знайома, дозволить кілька послідовних операцій «дістати» проти одного мутексу ОС, доки вони всі з одного контексту потоку. Багаторазове отримання має бути замінено рівним числом ставок, перш ніж інша нитка буде дозволена для отримання мютексу. Це відрізняється від бінарних семафорів, для яких дозволено одночасне отримання одночасно, незалежно від контексту потоку.

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

{
    mutexGet();  // Other threads can no longer get the mutex.

    // Make changes to the protected object.
    // ...

    objectModify();  // Also gets/puts the mutex.  Only allowed from this thread context.

    // Make more changes to the protected object.
    // ...

    mutexPut();  // Finally allows other threads to get the mutex.
}

Звичайно, користуючись цією функцією, ви повинні бути впевнені, що всі звернення в межах однієї нитки справді є безпечними!

Я не впевнений, наскільки поширений такий підхід чи застосовується він поза системами, з якими я знайомий. Для прикладу такого роду mutex див. RTOS ThreadX.


2
Вигляд мутексу, про який ви говорите, називається "рекурсивна мютекс", і цього слід уникати, оскільки вони повільні і, як правило, сприяють поганому дизайну: (див. Девід Бутенхоф: zaval.org/resources/library/butenhof1.html )
gaspard

Домовились. У цій конкретній ОС я використовую службу mutex, де хочу пояснити, що код призначений для "взаємного виключення", а не підрахунку посилань, але я не використовую рекурсивну функцію для страху перед некрасивим розкручуванням. Але в контексті питання це важлива різниця між "мутекс" та "бінарний семафор".
Кейсі Баркер

1

Мутекси мають право власності, на відміну від семафорів. Хоча будь-який потік, що знаходиться в межах mutex, може отримати розблокований мютекс і заблокувати доступ до одного і того ж критичного розділу коду, тільки нитка, що заблокувала мютекс, повинна розблокувати його .


Ви маєте на увазі контекст, який набуває мьютекс, може лише зняти його.
Раульп

1

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

Використовуючи семафор, ви можете змусити нитку зачекати на семафорі (скажімо, потік А), поки інша нитка (скажімо, нитка В) не виконає будь-яке завдання, а потім встановить Семафор для потоку А, щоб зупинити очікування, і продовжити своє завдання.


1

Найкраще рішення

Єдина відмінність

1.Mutex -> блокування та розблокування перебувають у власності на потоці, що блокує мютекс.

2.Semaphore -> Немає права власності, тобто; якщо одна нитка викликає semwait (s), будь-який інший потік може викликати sempost (s), щоб зняти замок.


1

MUTEX

Донедавна єдиним сплячим замком у ядрі був семафор. Більшість користувачів семафорів створили семафор з кількістю одиниць і трактували їх як замок взаємного виключення - сплячу версію спін-блокування. На жаль, семафори є досить загальними і не обмежують використання. Це робить їх корисними для керування ексклюзивним доступом у неясних ситуаціях, таких як складні танці між ядром та простором користувачів. Але це також означає, що простіше блокувати важче, а відсутність примусових правил унеможливлює будь-який тип автоматизованої налагодження чи виконання обмежень. Шукаючи більш простий замок для сну, розробники ядра представили mutex. Так, як ви звикли, це заплутане ім'я. Давайте уточнимо. Термін "мютекс" - це загальна назва для позначення будь-якого сплячого замка, який вимагає взаємного виключення, наприклад, семафор з кількістю використання. В останніх ядрах Linux власне іменник "mutex" тепер також є специфічним типом сплячого блоку, який реалізує взаємне виключення.

Простота та ефективність мютексу випливають із додаткових обмежень, які він накладає на своїх користувачів понад і вище, ніж вимагає семафор. На відміну від семафору, який реалізує найосновніше поведінку згідно з оригінальним дизайном Дійкстри, мютекс має більш жорсткий і вузький випадок використання: n Лише одне завдання може утримувати мутекс одночасно. Тобто, кількість використання мютексу завжди одна.

  1. Хто заблокував мютекс, повинен розблокувати його. Тобто ви не можете заблокувати мютекс в одному контексті, а потім розблокувати його в іншому. Це означає, що mutex не підходить для складніших синхронізацій між ядром та простором користувача. Більшість випадків використання, однак, чисто заблокують та розблокують із того самого контексту.
  2. Рекурсивні замки та розблокування заборонені. Тобто, ви не можете рекурсивно набувати один і той же мютекс, і ви не можете розблокувати розблокований мютекс.
  3. Процес не може вийти, зберігаючи мютекс.
  4. Мютекс не може бути придбаний обробником переривання або нижньою половиною, навіть із mutex_trylock ().
  5. Керувати мутексним файлом можна лише за допомогою офіційного API: його потрібно ініціалізувати за допомогою методів, описаних у цьому розділі, і не можна їх копіювати, вручну ініціалізувати чи реініціалізувати.

[1] Розробка ядра Linux, Третє видання Роберт Лав


1

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

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

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