Różnica między semaforem binarnym a muteksem


819

Czy jest jakaś różnica między binarnym semaforem a muteksem, czy są one zasadniczo takie same?


11
Są semantycznie takie same, ale w praktyce zauważysz dziwne różnice (szczególnie w systemie Windows).
Michael Foukarakis

5
@Michael Foukarakis: Jakie są dziwne różnice?
Philipp

2
Przypuszczam, że dziwne wyrażenie nie było prawidłowym wyrażeniem. Muteks obsługuje również własność, a czasem ponowne wejście. Tak jest w przypadku systemu Windows. Ponadto semafory w systemie Windows są zaimplementowane na obiektach Event, ale nie jestem pewien praktycznych konsekwencji tego.
Michael Foukarakis,


2
@philipxy Ładnie ukrył „rn” zamiast „m”.
Mooncrater,

Odpowiedzi:


691

NIE są tym samym. Są używane do różnych celów!
Podczas gdy oba typy semaforów mają pełny / pusty stan i używają tego samego interfejsu API, ich użycie jest bardzo różne.

Semafory wzajemnego wykluczania Semafory
wzajemnego wykluczania służą do ochrony wspólnych zasobów (struktura danych, plik itp.).

Semafor Mutex jest „własnością” zadania, które go podejmuje. Jeśli Zadanie B spróbuje semGive mutexu, który aktualnie znajduje się w Zadaniu A, wywołanie Zadania B zwróci błąd i zakończy się niepowodzeniem.

Muteksy zawsze używają następującej sekwencji:

  - SemTake
  - Krytyczny fragment
  - SemGive

Oto prosty przykład:

  Wątek A Wątek B
   Weź Mutex
     dane dostępowe
     ... Weź Mutex <== Zablokuje
     ...
   Podaj dane dostępu Mutex <== Odblokowuje
                                  ...
                                Daj Mutex

Seminary Binarne Semafory
binarne odnoszą się do zupełnie innego pytania:

  • Zadanie B oczekuje na oczekiwanie, aż coś się wydarzy (na przykład zadziałał czujnik).
  • Wyzwolenie czujnika i rutynowa procedura przerwania. Musi powiadomić zadanie o podróży.
  • Zadanie B powinno zostać uruchomione i podjąć odpowiednie działania dla wyłączenia czujnika. Następnie wróć do czekania.

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

Zauważ, że w przypadku binarnego semafora B może wziąć semafor, a A, aby go dać.
Ponownie, semafor binarny NIE chroni zasobu przed dostępem. Akt dawania i przyjmowania semafora jest zasadniczo oddzielony.
Zwykle nie ma sensu, aby to samo zadanie dawało i przyjmowało ten sam binarny semafor.


12
Czy zatem muteks nie jest lepszy niż semafor binarny? Ponieważ nie ma to sensu, jeśli ktoś zwolni zamek, którego tak naprawdę nie trzyma.
Pacerier

111
Mają różne cele. Mutex zapewnia wyłączny dostęp do zasobów. Do synchronizacji należy użyć binarnego semafora (tj. „Hej, ktoś! To się zdarzyło!”). Binarny „dawca” po prostu powiadamia każdego „biorcę”, że to, na co czekali, wydarzyło się.
Benoit,

5
@Pacerier Mylisz cel. Muteks ma chronić region krytyczny. Masz rację, nie ma sensu używać semafora binarnego. Zaktualizuję odpowiedź, aby wyjaśnić cel każdego z nich.
Benoit,

4
@Benoit Czy możemy więc powiedzieć, że Mutex są używane do atomowości i semafora binarnego dla perspektywy zamawiania, ponieważ zadanie B będzie czekało, aż zadanie A zasygnalizuje zwolnienie blokady z natury, upewniając się, że porządkuje operacje na strukturze danych?
abhi

1
@abhi To dobry sposób, aby na to spojrzeć w Mutex. Jednak w zależności od systemu operacyjnego na semaforze binarnym może czekać więcej niż jeden adresat. W takim przypadku tylko jeden klient otrzyma sem binarny. Inni czekają na kolejny. Czy kolejność otrzymywania jest znana czy gwarantowana? Zależy od systemu operacyjnego.
Benoit,

446
  • Mutex może być wydany jedynie przez wątek, który nabył go .
  • Binarny semafor może być sygnalizowane przez każdego gwintu (lub procesu).

więc semafory są bardziej odpowiednie w przypadku niektórych problemów z synchronizacją, takich jak producent-konsument.

W systemie Windows semafory binarne bardziej przypominają obiekty zdarzeń niż muteksy.


34
Mutex can be released only by thread that had acquired it- Właśnie próbowałem z prostym programem opartym na pthread_mutex, wątek może odblokować muteks zablokowany w głównym wątku
daisy

15
@ warl0ck Jak na stronie podręcznika man pthread_mutex_lock linux.die.net/man/3/pthread_mutex_lock : "Jeśli typem mutex jest PTHREAD_MUTEX_ERRORCHECK, należy sprawdzić błędy ... Jeśli wątek spróbuje odblokować muteks, który ma niezablokowany lub odblokowany muteks, zostanie zwrócony błąd. ”
dniu

47
@ warl0ck Patrz stackoverflow.com/a/5492499/385064 'Pthreads ma 3 różne rodzaje muteksów: szybki muteks, muteks rekurencyjny i muteks sprawdzania błędów. Użyłeś szybkiego muteksu, który ze względu na wydajność nie będzie sprawdzał tego błędu. Jeśli użyjesz mutex do sprawdzania błędów w systemie Linux, zobaczysz, że uzyskasz oczekiwane wyniki.
FrostNovaZzz

1
W naszym kodzie używaliśmy muteksu również do celów synchronizacji. Wątek, który blokuje muteks, ponownie próbował zablokować muteks, a następnie przechodzi do stanu zablokowanego. Widzieliśmy, że jesteśmy w stanie odblokować to z innego wątku. synchronizacja między nimi. Używamy tylko standardu POSIX. Więc główna różnica między mutexem a binarnym semaforem wydaje się niejasna.
achoora

1
@ achoora Zgadzam się, że źle jest specjalizować semafor do synchronizacji. W rzeczywistości wszystkie muteksy, semafory binarne, bariery i rurociągi mają różne wzorce synchronizacji. W perspektywie projektowania muteks bardziej przypominają wzorzec stanu, w którym algorytm wybrany przez stan może zmienić stan. Semafor binarny bardziej przypomina wzorzec strategii, w którym algorytm zewnętrzny może zmienić stan, a ostatecznie algorytm / strategię wybraną do uruchomienia.
shuva

442

Przykład toalety jest przyjemną analogią:

Mutex:

Jest kluczem do toalety. Jedna osoba może mieć w tym czasie klucz - zajmować toaletę. Po zakończeniu osoba daje (uwalnia) klucz następnej osobie w kolejce.

Oficjalnie: „Muteksy są zwykle używane do szeregowania dostępu do sekcji kodu ponownego wprowadzania, którego nie można wykonać jednocześnie przez więcej niż jeden wątek. Obiekt mutex pozwala tylko jednemu wątkowi na kontrolowaną sekcję, zmuszając inne wątki, które próbują uzyskać dostęp do tej sekcji, aby poczekać, aż pierwszy wątek opuści tę sekcję. ” Patrz: Symbian Developer Library

(Muteks to tak naprawdę semafor o wartości 1.)

Semafor:

Jest liczbą bezpłatnych identycznych kluczy toaletowych. Powiedzmy, że mamy cztery toalety z identycznymi zamkami i kluczami. Liczba semaforów - liczba kluczy - na początku jest ustawiona na 4 (wszystkie cztery toalety są wolne), następnie wartość zliczania jest zmniejszana w miarę wchodzenia ludzi. Jeśli wszystkie toalety są pełne, tj. nie ma już wolnych kluczy, liczba semaforów wynosi 0. Teraz, kiedy eq. jedna osoba opuszcza toaletę, semafor jest zwiększany do 1 (jeden wolny klucz) i przekazywany kolejnej osobie w kolejce.

Oficjalnie: „Semafor ogranicza liczbę jednoczesnych użytkowników współdzielonego zasobu do maksymalnej liczby. Wątki mogą żądać dostępu do zasobu (zmniejszanie semafora) i mogą sygnalizować, że zakończyły korzystanie z zasobu (zwiększając semafor). „ Patrz: Symbian Developer Library


234
... ale dotyczy to muteksu vs liczenia semafora. Pytanie dotyczyło binarnego.
Roman Nikitchenko,

24
Chociaż to, co powiedział David, jest poprawne, ale NIE jest to odpowiedź na zadane pytanie. Odpowiedź Mladena Jankovica jest odpowiedzią na zadane pytanie, w którym należy rozróżnić „semafor binarny” od „muteksu”.
Ajeet Ganga

13
Niestety, ta nieprawidłowa odpowiedź ma więcej głosów niż najlepsza odpowiedź @Benoit
NeonGlow,

6
Ta odpowiedź jest myląca. Powinien był być porównywany tylko z semaforem binarnym.
Hemanth

3
Pokazuje to również problem z użyciem semafora zliczającego do ochrony współdzielonego zasobu: jeśli klucze są rzeczywiście identyczne, a toaleta jest odblokowywana za pomocą klucza, a nie ma innego mechanizmu rozdzielającego użycie kabiny, to: (1) pierwszy użytkownik odblokowuje, wchodzi i zaczyna korzystać z pierwszej kabiny. (2) następny użytkownik odblokowuje, wchodzi i zaczyna korzystać z pierwszej kabiny ...
Technophile

151

Ładne artykuły na ten temat:

Od części 2:

Muteks jest podobny do zasad semafora binarnego z jedną istotną różnicą: zasadą własności. Własność to prosta koncepcja, że ​​gdy zadanie blokuje (nabywa) muteks, tylko on może go odblokować (zwolnić). Jeśli zadanie próbuje odblokować muteks, którego nie zablokował (a zatem nie jest właścicielem), napotkany zostanie warunek błędu i, co najważniejsze, muteks nie zostanie odblokowany. Jeśli obiekt wzajemnego wykluczenia nie ma prawa własności, bez względu na to, jak się nazywa, nie jest muteksem.


Dzięki za link, wyjaśnienia są doskonałe. Link się zmienił: feabhas.com/blog/2009/09/… (Użyj <Wstecz i Dalej>, aby przejść do pozostałych dwóch artykułów.
Aaron H.

@Aaron Naprawiłem linki
sędzia Maygarden

Uwaga - brak własności uniemożliwia również systemowi operacyjnemu obejście odwrócenia priorytetu. Z tego powodu generalnie używam zmiennych warunkowych w przeciwieństwie do semaforów w architekturze producenta / konsumenta.
kgriffs

1
+1 przeciwnik doskonałe linki do artykułów. Najlepszy artykuł wyjaśniający semafor i muteks za pomocą „what-it-is” i „what-it-does” computing.llnl.gov/tutorials/pthreads Użyłem tego artykułu jako odniesienia do sceny, który technicznie wyjaśnia wszystko o mutex / warunkowe i inne konstrukcje zbudowane na ich szczytach, takie jak semafor / bariera / czytnik-pisarz, ale nigdzie nie są jednoznaczne i zwięzłe na temat problemów napotykanych przez konstrukty. W skrócie jest to odniesienie. :)
Ajeet Ganga

łatwiejsze do zrozumienia niż inne odpowiedzi.
BinaryTreeee

101

Ponieważ żadna z powyższych odpowiedzi nie usuwa zamieszania, oto jedna, która wyjaśniła moje zamieszanie.

Ściśle mówiąc, muteks to mechanizm blokujący używany do synchronizacji dostępu do zasobu. Tylko jedno zadanie (może być wątkiem lub procesem opartym na abstrakcji systemu operacyjnego) może uzyskać muteks. Oznacza to, że z mutexem będzie związana własność i tylko właściciel może zwolnić blokadę (mutex).

Semafor to mechanizm sygnalizacyjny ( sygnał „Jestem skończony, możesz kontynuować”). Na przykład, jeśli słuchasz piosenek (zakładając, że to jedno zadanie) na telefonie komórkowym, a jednocześnie dzwoni do ciebie znajomy, zostanie uruchomione przerwanie, po którym procedura obsługi przerwania (ISR) zasygnalizuje, że zadanie przetwarzania połączenia zostanie pobudzone .

Źródło: http://www.geeksforgeeks.org/mutex-vs-semaphore/


42

Ich semantyka synchronizacji jest bardzo różna:

  • muteksy umożliwiają serializację dostępu do danego zasobu, tzn. wiele wątków czeka na blokadę, jeden po drugim i jak wcześniej wspomniano, wątek jest właścicielem blokady, dopóki nie zostanie wykonana: tylko ten konkretny wątek może ją odblokować.
  • semafor binarny jest licznikiem o wartości 0 i 1: zadanie blokuje go, dopóki dowolne zadanie nie wykona sem_post. Semafor informuje, że zasób jest dostępny, i zapewnia mechanizm oczekiwania, aż zostanie zasygnalizowany jako dostępny.

Jako taki można zobaczyć muteks jako token przekazywany z zadania do zadania, a semafor jako czerwone światło ruchu ( sygnalizuje komuś, że może kontynuować).


23

Na poziomie teoretycznym nie różnią się one semantycznie. Możesz zaimplementować muteks za pomocą semaforów lub odwrotnie (zobacz tutaj przykład). W praktyce wdrożenie jest inne i oferują nieco inne usługi.

Praktyczną różnicą (pod względem otaczających je usług systemowych) jest to, że implementacja muteksu ma na celu być lżejszym mechanizmem synchronizacji. W oracle-speak muteksy nazywane są zatrzaskami, a semafory - czekaniami .

Na najniższym poziomie używają pewnego rodzaju testu atomowego i ustawiają mechanizm. Odczytuje bieżącą wartość lokalizacji w pamięci, oblicza pewien warunek i zapisuje wartość w tej lokalizacji w pojedynczej instrukcji, której nie można przerwać . Oznacza to, że możesz zdobyć muteks i przetestować, czy ktoś jeszcze go miał.

Typowa implementacja muteksu ma proces lub wątek wykonujący instrukcję testowania i ustawiania oraz oceniający, czy coś innego ustawiło muteks. Kluczową kwestią jest tutaj brak interakcji z harmonogramem , więc nie mamy pojęcia (i nie obchodzi nas), kto ustawił blokadę. Następnie albo rezygnujemy z wycinka czasu i próbujemy go ponownie, gdy zadanie zostanie ponownie zaplanowane, albo wykonamy blokadę . Blokada spinowa to algorytm taki jak:

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.

Po zakończeniu wykonywania naszego chronionego kodu (znanego jako sekcja krytyczna ) po prostu ustawiamy wartość muteksu na zero lub cokolwiek innego, co oznacza „wyczyść”. Jeśli wiele zadań próbuje uzyskać muteks, następne zadanie, które zdarzy się zaplanowane po zwolnieniu muteksu, uzyska dostęp do zasobu. Zazwyczaj używasz muteksów do kontrolowania zsynchronizowanego zasobu, w którym wyłączny dostęp jest potrzebny tylko przez bardzo krótkie okresy, zwykle w celu dokonania aktualizacji wspólnej struktury danych.

Semafor jest zsynchronizowaną strukturą danych (zwykle używającą muteksu), która ma liczbę i niektóre opakowania wywołań systemowych, które oddziałują z harmonogramem na nieco większej głębokości niż biblioteki mutexów. Semafory są zwiększane i zmniejszane i używane do blokowania zadań, dopóki coś innego nie będzie gotowe. Zobacz przykład producenta / konsumenta, aby uzyskać prosty przykład tego. Semafory są inicjowane do pewnej wartości - semafor binarny jest tylko specjalnym przypadkiem, w którym semafor jest inicjowany na 1. Księgowanie na semaforze powoduje przebudzenie procesu oczekiwania.

Podstawowy algorytm semaforów wygląda następująco:

(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.

W przypadku semafora binarnego główną praktyczną różnicą między nimi jest charakter usług systemowych otaczających faktyczną strukturę danych.

EDYCJA: Jak słusznie zauważył Evan, blokady spinowe spowolnią maszynę z jednym procesorem. Używałbyś tylko spinlocka na pudełku wieloprocesorowym, ponieważ na jednym procesorze proces trzymający muteks nigdy go nie zresetuje, gdy uruchomione jest inne zadanie. Blokady są przydatne tylko w architekturach wieloprocesorowych.


1
Nie sądzę, że powszechną praktyką jest stosowanie muteksu za pomocą spinlocków. Na maszynie Uni-proc byłoby to absolutnie straszne z punktu widzenia wydajności.
Evan Teran,

Zwykle spinlocków używa się tylko w systemach wieloprocesorowych.
ConcernedOfTunbridgeWells

Nawet w przypadku SMP po kilkukrotnym przestawieniu się wrócisz do trybu uśpienia / czuwania wspomaganego przez system operacyjny. (np. futexistnieje systemowe wywołanie systemu Linux , które pomaga w implementacji mutex / semaforów w przestrzeni użytkownika o niskim opóźnieniu. en.wikipedia.org/wiki/Futex ) W szybkiej ścieżce bez rywalizacji lub jeśli zasób stanie się wkrótce dostępny, nigdy nie będziesz mieć narzutu wywołanie systemowe. Ale nie spędzasz więcej niż kilka mikrosekund na czekaniu (wirowanie). Strojenie parametrów wycofywania i oczekiwania pętli spinowej jest oczywiście zależne od sprzętu i obciążenia, ale biblioteka standardowa ma zwykle rozsądny wybór.
Peter Cordes

19

Chociaż muteksy i semafory są używane jako prymitywy synchronizacji, istnieje między nimi duża różnica. W przypadku muteksu tylko wątek, który zablokował lub nabył muteks, może go odblokować. W przypadku semafora wątek oczekujący na semafor może być sygnalizowany przez inny wątek. Niektóre systemy operacyjne obsługują muteksy i semafory między procesami. Zazwyczaj użycie jest tworzone we wspólnej pamięci.


„może być sygnalizowany przez inny wątek”, co to znaczy podać przykład.
Myanju

15

Mutex: Załóżmy, że mamy wątek sekcji krytycznej T1 chce uzyskać do niego dostęp, a następnie wykonuje poniższe kroki. T1:

  1. Zamek
  2. Użyj sekcji krytycznej
  3. Odblokować

Semafor binarny: Działa w oparciu o sygnalizację oczekiwania i sygnału. czekanie (s) zmniejszanie wartości „s” o jeden zwykle wartość „s” jest inicjalizowana wartością „1”, sygnał (-y) zwiększa wartość „s” o jeden. jeśli wartość „s” wynosi 1, oznacza to, że nikt nie używa sekcji krytycznej, gdy wartość wynosi 0, oznacza to, że sekcja krytyczna jest w użyciu. załóżmy, że gwint T2 używa sekcji krytycznej, a następnie wykonuje poniższe kroki. T2:

  1. wait (s) // początkowo wartość wynosi jeden po wywołaniu wait, jego wartość zmniejszyła się o jeden, tj. 0
  2. Użyj sekcji krytycznej
  3. signal (s) // teraz wartość jest zwiększona i staje się 1

Główna różnica między Mutex a semaforem binarnym polega na tym, że jeśli wątek blokuje sekcję krytyczną, to musi odblokować sekcję krytyczną, żaden inny wątek nie może jej odblokować, ale w przypadku semafora binarnego, jeśli jeden wątek blokuje sekcję krytyczną za pomocą funkcji oczekiwania (ów), wówczas wartość z s staje się „0” i nikt nie może uzyskać do niego dostępu, dopóki wartość „s” nie zmieni się na 1, ale załóżmy, że niektóre inne sygnały wywołania wątku to (s), a następnie wartość „s” staje się 1 i pozwala innej funkcji na użycie sekcji krytycznej. dlatego w binarnym wątku semaforowym nie ma własności.


12

W systemie Windows istnieją dwie różnice między muteksami a semaforami binarnymi:

  1. Muteks może zostać zwolniony tylko przez wątek, który ma własność, tj. Wątek, który wcześniej wywoływał funkcję Wait (lub który przejął własność podczas jej tworzenia). Semafor może zostać zwolniony przez dowolny wątek.

  2. Wątek może wielokrotnie wywoływać funkcję oczekiwania na muteksie bez blokowania. Jeśli jednak wywołasz funkcję oczekiwania dwa razy w semaforze binarnym bez zwalniania semafora pomiędzy nimi, wątek zostanie zablokowany.


4
Dobra odpowiedź. W punkcie 2 opisujesz rekurencyjny muteks - nie wszystkie muteksy są koniecznie rekurencyjne. Np. Cs.wustl.edu/~schmidt/ACE.FAQ.html#Q14
Dan

10

Oczywiście używasz mutexu do blokowania danych w jednym wątku, do których dostęp uzyskuje inny wątek w tym samym czasie. Załóżmy, że właśnie zadzwoniłeś lock()i uzyskujesz dostęp do danych. Oznacza to, że nie oczekujesz, że żaden inny wątek (lub inna instancja tego samego kodu wątku) uzyska dostęp do tych samych danych zablokowanych przez ten sam muteks. Oznacza to, że jeśli ten sam kod wątku jest wykonywany w innej instancji wątku, uderza w blokadę, a następnielock()powinien tam zablokować przepływ kontrolny. Dotyczy to wątku, który używa innego kodu wątku, który również uzyskuje dostęp do tych samych danych i który jest również zablokowany przez ten sam muteks. W takim przypadku nadal uzyskujesz dostęp do danych i możesz zająć, powiedzmy, kolejne 15 sekund, aby dotrzeć do odblokowania muteksu (tak, aby inny wątek, który jest blokowany w blokadzie mutexów, odblokowałby się i pozwolił kontroli dostęp do danych). Czy za wszelką cenę pozwalasz, aby kolejny wątek po prostu odblokował ten sam muteks, a z kolei pozwala wątkowi, który już czeka (blokuje) w zamku mutex, aby odblokować i uzyskać dostęp do danych? Mam nadzieję, że masz to, co mówię tutaj? Zgodnie z ustaloną uniwersalną definicją !,

  • z „mutex” to się nie może zdarzyć. Żaden inny wątek nie może odblokować blokady w tym wątku
  • z „semaforem binarnym” może się to zdarzyć. Każdy inny wątek może odblokować blokadę w tym wątku

Tak więc, jeśli jesteś bardzo konkretny w używaniu semafora binarnego zamiast muteksu, powinieneś być bardzo ostrożny w „scopowaniu” blokad i odblokowań. Chodzi mi o to, że każdy przepływ kontroli, który uderza w każdą blokadę, powinien uderzyć w polecenie odblokowania, również nie powinno być żadnego „pierwszego odblokowania”, a raczej zawsze powinna to być „pierwsza blokada”.


10

Mutex stosuje się w „Mechanizmach blokujących”. jeden proces na raz może korzystać ze współdzielonego zasobu

natomiast

Semafory są używane w „Mechanizmach sygnalizacyjnych”, np. „Skończyłem, teraz mogę kontynuować”


9

Mit:

Kilka artykułów mówi, że „binarny semafor i muteks są takie same” lub „Semafor o wartości 1 to muteks”, ale podstawową różnicą jest to, że Mutex można zwolnić tylko przez wątek, który go nabył, a semafor można zasygnalizować z dowolnego innego wątku

Kluczowe punkty:

• Wątek może uzyskać więcej niż jeden zamek (Mutex).

• Muteks może zostać zablokowany więcej niż jeden raz, jeśli jest to muteks rekurencyjny, tutaj blokowanie i odblokowywanie muteksu powinno być takie samo

• Jeśli wątek, który już zablokował muteks, spróbuje ponownie zablokować muteks, przejdzie do listy oczekujących tego muteksu, co spowoduje zakleszczenie.

• Binarny semafor i muteks są podobne, ale nie takie same.

• Mutex jest kosztownym działaniem ze względu na związane z nim protokoły ochrony.

• Głównym celem mutex jest osiągnięcie dostępu atomowego lub zablokowanie zasobów


8

Mutex kontroluje dostęp do jednego zasobu wspólne. Zapewnia operacje mające na celu uzyskanie () dostępu do tego zasobu i zwolnienie () go po zakończeniu.

Semafor kontroluje dostęp do wspólnej puli zasobów. Zapewnia operacje do Wait (), aż jeden z zasobów w puli stanie się dostępny, i Signal (), gdy zostanie zwrócony do puli.

Gdy liczba zasobów, które chroni Semafor, jest większa niż 1, nazywa się to Semaforem zliczającym . Gdy kontroluje jeden zasób, nazywa się to semaforem boolowskim . Logiczny semafor jest równoważny muteksowi.

Zatem semafor jest abstrakcją wyższego poziomu niż Mutex. Mutex można wdrożyć za pomocą semafora, ale nie na odwrót.


6

Zmodyfikowane pytanie brzmi - jaka jest różnica między muteksem a semaforem „binarnym” w „Linuksie”?

Odp .: Poniżej przedstawiono różnice - i) Zakres - Zakres muteksu znajduje się w przestrzeni adresowej procesu, która go utworzyła i służy do synchronizacji wątków. Natomiast semafor może być wykorzystywany w przestrzeni procesu, a zatem może być wykorzystywany do synchronizacji międzyprocesowej.

ii) Mutex jest lekki i szybszy niż semafor. Futex jest jeszcze szybszy.

iii) Mutex może być nabyty przez ten sam wątek wiele razy, pod warunkiem, że zwolni go tyle razy. Inny wątek, który próbuje zdobyć, zostanie zablokowany. Natomiast w przypadku semafora, jeśli ten sam proces próbuje go odzyskać, blokuje, ponieważ można go zdobyć tylko raz.


mylę się. ii) Źródło? iii) To zależy.
ciekawy,

6

Zróżnicowanie między semaforem binarnym a mutexem: WŁASNOŚĆ: semafory mogą być sygnalizowane (wysyłane) nawet od nie aktualnego właściciela. Oznacza to, że możesz po prostu publikować posty z dowolnego innego wątku, chociaż nie jesteś właścicielem.

Semafor jest własnością publiczną w toku, może być po prostu opublikowany przez wątek niebędący właścicielem. Proszę zaznaczyć tę różnicę BOLD, to wiele znaczy.


5

Mutex pracuje nad blokowaniem krytycznego regionu, ale Semafor działa na zasadzie liczenia.



4

Oprócz faktu, że muteksy mają właściciela, oba obiekty mogą być zoptymalizowane do różnych zastosowań. Muteksy są zaprojektowane tak, aby można je było przetrzymywać tylko przez krótki czas; naruszenie tego może spowodować niską wydajność i nieuczciwe planowanie. Na przykład uruchomiony wątek może uzyskać muteks, nawet jeśli inny wątek jest już na nim zablokowany. Semafory mogą zapewniać większą uczciwość lub sprawiedliwość można wymusić za pomocą kilku zmiennych warunkowych.


W jakich konkretnych przypadkach zagwarantowana jest sprawiedliwość dla semaforów, ale nie dla muteksów?
ciekawy

1
POSIX ma określone wymagania, przez które wątek powinien zostać przebudzony sem_post()dla SCHED_FIFOiSCHED_RR (oba te nie są domyślnie): najwyższy priorytet wątku, a jeśli istnieje wiele o tym samym priorytecie, wątek, który został czekają najdłużej. OpenSolaris w pewnym stopniu przestrzega tej zasady FIFO, nawet przy normalnym planowaniu. W przypadku glibc i FreeBSD odblokowanie prostego muteksu (tj. Bez ochrony priorytetowej lub dziedziczenia priorytetowego) i wysłanie semafora jest w zasadzie takie samo, oznaczając obiekt jako odblokowany, a następnie, jeśli mogą istnieć oczekujące wątki, wywołuje jądro, aby je obudzić.
jilles

4

W systemie Windows różnica jest jak poniżej. MUTEX: proces, który pomyślnie wykonuje oczekiwanie, musi wykonać sygnał i odwrotnie. SEMAFERY BINARNE: Różne procesy mogą wykonywać operacje oczekiwania lub sygnalizacji na semaforze.


4

Podczas gdy binarny semafor może być użyty jako muteks, muteks jest bardziej konkretnym przypadkiem użycia, w którym tylko proces, który zablokował muteks, powinien go odblokować. To ograniczenie własności umożliwia ochronę przed:

  • Przypadkowe uwolnienie
  • Recursive Deadlock
  • Zadanie Death Deadlock

Te ograniczenia nie zawsze są obecne, ponieważ zmniejszają prędkość. Podczas opracowywania kodu możesz tymczasowo włączyć te kontrole.

np. możesz włączyć atrybut sprawdzania błędów w swoim muteksie. Błąd sprawdzania muteksów powraca, EDEADLKjeśli spróbujesz dwa razy to samo zablokować i EPERModblokujesz muteks, który nie jest twój.

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);

Po zainicjowaniu możemy umieścić następujące kontrole w naszym kodzie:

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

4

Ta koncepcja była dla mnie jasna po przejściu powyżej postów. Ale pojawiło się kilka długich pytań. Więc napisałem ten mały fragment kodu.

Kiedy próbujemy dać semafor bez jego przyjmowania, to przechodzi. Ale kiedy próbujesz dać muteksowi bez jego przyjmowania, to się nie udaje. Przetestowałem to na platformie Windows. Włącz USE_MUTEX, aby uruchomić ten sam kod za pomocą 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;
}

Sam fakt, że semafor pozwala zasygnalizować, że „odbywa się to za pomocą zasobu”, mimo że nigdy nie był właścicielem zasobu, sprawia, że ​​uważam, że istnieje bardzo luźne powiązanie między posiadaniem a sygnalizowaniem w przypadku semaforów.


Jeśli przeczytasz inne odpowiedzi, jasne jest, że pojęcie „własności” ma sens tylko w przypadku muteksów, a nie semaforów. Semafory mogą być użyte do takich rzeczy jak wątek informujący inne wątki, że przetwarzanie części danych jest zakończone; wyniki gotowe do odczytu.
Peter Cordes

2

Mutex służy do ochrony wrażliwego kodu i danych, semafor służy do synchronizacji. Możesz również mieć praktyczne zastosowanie do ochrony wrażliwego kodu, ale może istnieć ryzyko, że zwolni ochronę przez inny wątek przez operację V. Tak więc Główny różnica między bi-semaforem a muteksem jest własnością. Na przykład przez toaletę Mutex jest taki, że można wejść do toalety i zamknąć drzwi, nikt inny nie może wejść, dopóki mężczyzna nie wyjdzie, bi-semafor jest taki, jak można wejść Toaleta i zamknąć drzwi, ale ktoś inny mógłby wejść, prosząc administratora o otwarcie drzwi, to niedorzeczne.


2

Mutex

Muteksy są zwykle używane do szeregowania dostępu do sekcji kodu ponownego wprowadzania, którego nie można wykonać jednocześnie przez więcej niż jeden wątek. Obiekt mutex pozwala tylko jednemu wątkowi na kontrolowaną sekcję, zmuszając inne wątki, które próbują uzyskać dostęp do tej sekcji, aby czekały, aż pierwszy wątek opuści tę sekcję. Właściwe użycie muteksu w celu ochrony udostępnionego zasobu może mieć niebezpieczne niezamierzony efekt uboczny. Wszelkie dwa zadania RTOS, które działają z różnymi priorytetami i koordynują za pomocą muteksu, stwarzają możliwość inwersji priorytetów . Mutex działa w przestrzeni użytkownika .

Semafor

Semafor jest mechanizmem sygnalizacyjnym. Semafor ogranicza liczbę jednoczesnych użytkowników współdzielonego zasobu do maksymalnej liczby. Wątki mogą żądać dostępu do zasobu (zmniejszanie semafora) i mogą sygnalizować, że zakończyły korzystanie z zasobu (zwiększając semafor). Umożliwia dostęp do współdzielonych zasobów liczbie wątków. Prawidłowe użycie semafora służy do sygnalizowania z jednego zadania do drugiego. Semaforów można również używać do sygnalizowania z procedury usługi przerwań (ISR) do zadania. Sygnalizacja semafora jest nieblokującym zachowaniem RTOS i dlatego jest bezpieczna dla ISR. Ponieważ ta technika eliminuje podatną na błędy potrzebę wyłączania przerwań na poziomie zadania, działa to w przestrzeni jądra .


1

Odpowiedź może zależeć od docelowego systemu operacyjnego. Na przykład, przynajmniej jedna implementacja RTOS, którą znam, pozwoli na wielokrotne sekwencyjne operacje „get” przeciwko pojedynczemu muteksowi systemu operacyjnego, o ile wszystkie są w tym samym kontekście wątku. Wielokrotne pobranie musi zostać zastąpione taką samą liczbą putów, zanim inny wątek będzie mógł uzyskać muteks. Różni się to od semaforów binarnych, dla których dozwolony jest tylko jeden get na raz, niezależnie od kontekstu wątku.

Idea tego rodzaju muteksu polega na tym, że chronisz obiekt, umożliwiając modyfikowanie danych tylko w jednym kontekście. Nawet jeśli wątek pobiera muteks, a następnie wywołuje funkcję, która dalej modyfikuje obiekt (i pobiera / umieszcza muteks ochronny wokół własnych operacji), operacje powinny nadal być bezpieczne, ponieważ wszystkie one odbywają się pod jednym wątkiem.

{
    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.
}

Oczywiście, korzystając z tej funkcji, musisz mieć pewność, że wszystkie dostępy w ramach jednego wątku są naprawdę bezpieczne!

Nie jestem pewien, jak powszechne jest to podejście, ani czy ma ono zastosowanie poza systemami, które znam. Aby zobaczyć przykład tego rodzaju muteksu, zobacz ThreadX RTOS.


2
Rodzaj muteksu, o którym mówisz, nazywa się „rekurencyjnym muteksem” i należy go unikać, ponieważ są powolne i mają tendencję do promowania złego projektu: (patrz David Butenhof: zaval.org/resources/library/butenhof1.html )
gaspard

Zgoda. W tym konkretnym systemie operacyjnym korzystam z usługi mutex, w której chcę wyjaśnić, że kod służy do „wzajemnego wykluczania”, a nie liczenia referencji, ale nie używam funkcji rekurencyjnej z obawy przed brzydkim odwijaniem. Mimo to w kontekście pytania jest to istotna różnica między „mutexem” a „binarnym semaforem”.
Casey Barker,

1

Muteksy mają własność, w przeciwieństwie do semaforów. Chociaż dowolny wątek w zakresie muteksu może uzyskać odblokowany muteks i zablokować dostęp do tej samej krytycznej sekcji kodu, tylko wątek, który zablokował muteks, powinien go odblokować .


co to jest własność? Masz na myśli kontekst, w którym nabywa się mutex, można go tylko cofnąć.
Raulp

1

Jak wspomniało tu wielu ludzi, muteks służy do ochrony krytycznego fragmentu kodu (sekcja krytyczna AKA). Zdobędziesz muteks (blokada), wejdziesz w sekcję krytyczną i zwolnisz mutex (odblokuj) w tym samym wątku .

Korzystając z semafora, możesz sprawić, aby wątek czekał na semaforze (powiedz wątek A), aż inny wątek (powiedzmy wątek B) wykona dowolne zadanie, a następnie ustawi semafor dla wątku A, aby przerwał oczekiwanie i kontynuował swoje zadanie.


1

Najlepsze rozwiązanie

Jedyna różnica to

1.Mutex -> zablokuj i odblokuj są własnością wątku, który blokuje muteks.

2.Safafor -> Brak własności tj. jeśli jeden wątek wywołuje semwait (s), każdy inny wątek może wywoływać sempost (s) w celu usunięcia blokady.


1

MUTEX

Do niedawna jedynym śpiącym zamkiem w jądrze był semafor. Większość użytkowników semaforów tworzyła semafor z liczbą jeden i traktowała je jako blokadę wzajemnego wykluczenia - sypialną wersję blokady spinowej. Niestety semafory są dość ogólne i nie nakładają żadnych ograniczeń użytkowania. To sprawia, że ​​są przydatne do zarządzania wyłącznym dostępem w mało znanych sytuacjach, takich jak skomplikowane tańce między jądrem a przestrzenią użytkownika. Ale oznacza to również, że prostsze blokowanie jest trudniejsze, a brak egzekwowanych reguł uniemożliwia jakiekolwiek automatyczne debugowanie lub wymuszanie ograniczeń. Szukając prostszej blokady do spania, programiści jądra wprowadzili mutex. Tak, jak jesteście przyzwyczajeni, to myląca nazwa. Wyjaśnijmy. Termin „mutex” to ogólna nazwa odnosząca się do każdego śpiącego zamka, który wymusza wzajemne wykluczenie, takie jak semafor z liczbą użycia równą jeden. W najnowszych jądrach Linuksa właściwy rzeczownik „mutex” jest teraz także specyficznym rodzajem blokady uśpienia, która realizuje wzajemne wykluczanie. Oznacza to, że muteks jest muteksem.

Prostota i wydajność muteksu wynika z dodatkowych ograniczeń, które nakłada na użytkowników ponad to, czego wymaga semafor. W przeciwieństwie do semafora, który realizuje najbardziej podstawowe zachowanie zgodnie z oryginalnym projektem Dijkstry, muteks ma bardziej rygorystyczny, węższy przypadek użycia: n Tylko jedno zadanie może przechowywać muteks jednocześnie. Oznacza to, że liczba użycia mutexa zawsze wynosi jeden.

  1. Ktokolwiek zablokował muteks, musi go odblokować. Oznacza to, że nie można zablokować muteksu w jednym kontekście, a następnie odblokować go w innym. Oznacza to, że mutex nie nadaje się do bardziej skomplikowanych synchronizacji między jądrem a przestrzenią użytkownika. Jednak większość przypadków użycia blokuje się i odblokowuje w tym samym kontekście.
  2. Blokady rekurencyjne i odblokowania są niedozwolone. Oznacza to, że nie można rekurencyjnie zdobyć tego samego muteksu i nie można odblokować odblokowanego muteksu.
  3. Proces nie może wyjść, gdy przechowywany jest muteks.
  4. Mutex nie może być nabyty przez moduł obsługi przerwań lub dolną połowę, nawet przy pomocy mutex_trylock ().
  5. Mutex można zarządzać tylko za pośrednictwem oficjalnego interfejsu API: musi być inicjowany metodami opisanymi w tej sekcji i nie może być kopiowany, inicjowany ręcznie ani ponownie inicjowany.

[1] Linux Kernel Development, trzecia edycja Robert Love


1

Myślę, że większość odpowiedzi tutaj była myląca, szczególnie te, które mówiły, że muteks może być uwolniony tylko przez proces, który go utrzymuje, ale semafor może być sygnalizowany przez dowolny proces. Powyższa linia jest niejasna pod względem semafora. Aby zrozumieć, powinniśmy wiedzieć, że istnieją dwa rodzaje semaforów, jeden nazywa się semaforem liczącym, a drugi semaforem binarnym. W liczeniu semafor obsługuje dostęp do n liczby zasobów, gdzie n można zdefiniować przed użyciem. Każdy semafor ma zmienną count, która utrzymuje liczbę używanych zasobów, początkowo jest ustawiona na n. Każdy proces, który chce użyć zasobu, wykonuje operację wait () na semaforze (zmniejszając w ten sposób liczbę). Gdy proces zwalnia zasób, wykonuje operację release () (zwiększając liczbę). Gdy liczba osiągnie 0, wszystkie zasoby są wykorzystywane. Następnie proces czeka, aż liczba osiągnie wartość większą niż 0. Teraz tutaj jest tylko proces, który przechowuje zasób może zwiększyć liczbę, żaden inny proces nie może zwiększyć liczby, tylko procesy przechowujące zasób mogą zwiększyć liczbę, a proces czekanie na semafor ponownie sprawdza, a kiedy widzi dostępny zasób, ponownie zmniejsza liczbę. Tak więc, jeśli chodzi o binarny semafor, tylko proces utrzymujący semafor może zwiększyć liczbę, a liczba pozostaje równa zero, dopóki nie przestanie używać semafora i zwiększy liczbę, a inny proces uzyska szansę na dostęp do semafora. Teraz jest haczyk, tylko proces, który przechowuje zasób może zwiększyć liczbę, żaden inny proces nie może zwiększyć liczby, tylko procesy przechowujące zasób mogą zwiększyć liczbę, a proces czekający na semafor ponownie sprawdza i kiedy widzi zasoby dostępne ponownie zmniejsza liczbę. Tak więc, jeśli chodzi o binarny semafor, tylko proces utrzymujący semafor może zwiększyć liczbę, a liczba pozostaje równa zero, dopóki nie przestanie używać semafora i zwiększy liczbę, a inny proces uzyska szansę na dostęp do semafora. Teraz jest haczyk, tylko proces, który przechowuje zasób może zwiększyć liczbę, żaden inny proces nie może zwiększyć liczby, tylko procesy przechowujące zasób mogą zwiększyć liczbę, a proces czekający na semafor ponownie sprawdza i kiedy widzi zasoby dostępne ponownie zmniejsza liczbę. Tak więc, jeśli chodzi o binarny semafor, tylko proces utrzymujący semafor może zwiększyć liczbę, a liczba pozostaje równa zero, dopóki nie przestanie używać semafora i zwiększy liczbę, a inny proces uzyska szansę na dostęp do semafora.

Główną różnicą między binarnym semaforem a muteksem jest to, że semafor jest mechanizmem sygnalizacyjnym, a muteks jest mechanizmem blokującym, ale semafor binarny wydaje się działać jak muteks, który powoduje zamieszanie, ale oba są różnymi koncepcjami odpowiednimi do różnych rodzajów pracy.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.