Kiedy powinniśmy używać muteksu, a kiedy semafora


Odpowiedzi:


93

Oto jak pamiętam, kiedy czego używać -

Semafor: Użyj semafora, gdy (wątek) chcesz spać, dopóki inny wątek nie powie ci, abyś się obudził. Semafor „down” dzieje się w jednym wątku (producent), a semafor „up” (dla tego samego semafora) dzieje się w innym wątku (konsument) np .: W przypadku problemu producent-konsument producent chce spać, dopóki przynajmniej jeden slot bufora nie będzie pusty - tylko wątek konsumenta może stwierdzić, kiedy gniazdo bufora jest puste.

Mutex: Użyj muteksu, gdy (wątek) chcesz wykonać kod, który nie powinien być wykonywany jednocześnie przez żaden inny wątek. Mutex „down” ma miejsce w jednym wątku, a mutex „up” musi nastąpić później w tym samym wątku. Np .: Jeśli usuwasz węzeł z globalnej listy połączonej, nie chcesz, aby inny wątek grzebał po wskaźnikach podczas usuwania węzła. Kiedy zdobędziesz muteks i jesteś zajęty usuwaniem węzła, jeśli inny wątek spróbuje uzyskać ten sam muteks, zostanie uśpiony, dopóki nie zwolnisz muteksu.

Spinlock: Użyj spinlocka, gdy naprawdę chcesz użyć muteksu, ale twoja nić nie może spać. Np .: Procedura obsługi przerwań w jądrze systemu operacyjnego nie może nigdy spać. Jeśli tak, system zawiesi się / ulegnie awarii. Jeśli chcesz wstawić węzeł do globalnie udostępnianej listy połączonej z obsługi przerwań, uzyskaj blokadę spinlock - węzeł wstawiania - zwolnij spinlock.


1
dodać do: semaforów i muteksu to dwa sposoby na zapewnienie synchronizacji. semafor, może być bardziej związany z sygnalizacją (np. scenariusz problemu producenta i konsumenta), a mutex, może być bardziej związany z umożliwieniem dostępu do jednego na raz (kilka żądań dostępu do współdzielonego zasobu, ale tylko jedno przyznawane na raz). [fajny artykuł: geeksforgeeks.org/mutex-vs-semaphore/]
parasrish

57

Muteks to obiekt wzajemnego wykluczania, podobny do semafora, ale dopuszczający w danym momencie tylko jedną szafkę, której ograniczenia własności mogą być bardziej rygorystyczne niż semafor.

Można go traktować jako równoważny zwykłemu semaforowi liczącemu (z liczbą jeden) i wymaganiem, aby mógł zostać zwolniony tylko przez ten sam wątek, który go zablokował (a) .

Z drugiej strony semafor ma dowolną liczbę i może być zablokowany przez tyle szafek jednocześnie. I może nie wymagać, aby został zwolniony przez ten sam wątek, który go zgłosił (ale jeśli nie, musisz dokładnie śledzić, kto jest obecnie za to odpowiedzialny, podobnie jak przydzielona pamięć).

Tak więc, jeśli masz kilka wystąpień zasobu (powiedzmy trzy napędy taśmowe), możesz użyć semafora z liczbą 3. Zauważ, że to nie mówi ci, który z tych napędów taśmowych masz, tylko że masz pewną liczbę.

Również w przypadku semaforów jedna szafka może blokować wiele wystąpień zasobu, na przykład w przypadku kopiowania z taśmy na taśmę. Jeśli masz jeden zasób (powiedzmy lokalizację pamięci, której nie chcesz uszkodzić), bardziej odpowiedni jest muteks.

Równoważne operacje to:

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

Poza tym: jeśli kiedykolwiek zastanawiałeś się nad dziwnymi literami używanymi do zgłaszania i zwalniania semaforów, to dlatego, że wynalazcą był Holender. Probeer te verlagen oznacza próbę zmniejszenia, podczas gdy verhogen oznacza wzrost.


(a) ... lub można go traktować jako coś zupełnie innego niż semafor, co może być bezpieczniejsze, biorąc pod uwagę ich prawie zawsze różne zastosowania.


OK, natknąłem się też na semafor binarny. Kiedy powinniśmy zacząć używać semafora binarnego, a kiedy mutex?
Karthik Balaguru

Koncepcyjnie semafor binarny jest muteksem i jest odpowiednikiem zwykłego semafora z licznikiem jeden. Mogą występować różnice w implementacji koncepcji, takie jak wydajność lub własność zasobu (może zostać zwolniony przez kogoś innego niż zgłaszający roszczenie, czego nie zgadzam się z BTW - zasób powinien być udostępniany tylko przez wątek, który go zgłosił ).
paxdiablo

1
Inną potencjalną różnicą w implementacji jest rekurencyjny mutex. Ponieważ istnieje tylko jeden zasób, pojedynczy wątek może mieć możliwość wielokrotnego blokowania go (o ile zwalnia go również tyle razy). Nie jest to takie proste w przypadku zasobu z wieloma instancjami, ponieważ możesz nie wiedzieć, czy wątek chce ponownie zażądać innej instancji, czy tej samej instancji.
paxdiablo

1
Rozwiązują konkretny problem. Fakt, że problem, który rozwiązują, to ludzie, którzy nie do końca grokują muteksy, w żaden sposób nie powinni umniejszać rozwiązania :-)
paxdiablo

5
Muteks jest zupełnie inny niż semafor binarny. Przepraszamy, ale ta definicja jest błędna
Peer Stritzinger

49

Bardzo ważne jest, aby zrozumieć, że mutex nie jest semaforem z liczbą 1!

To jest powód, dla którego istnieją takie rzeczy jak semafory binarne (które w rzeczywistości są semaforami z liczbą 1).

Różnica między muteksem a semaforem binarnym polega na zasadzie własności:

Mutex jest nabywany przez zadanie i dlatego musi być również zwolniony przez to samo zadanie. Umożliwia to naprawienie kilku problemów z semaforami binarnymi (przypadkowe zwolnienie, rekurencyjne zakleszczenie i odwrócenie priorytetu).

Uwaga: napisałem „umożliwia”, czy i jak te problemy zostaną naprawione, zależy od implementacji systemu operacyjnego.

Ponieważ mutex musi zostać zwolniony przez to samo zadanie, nie nadaje się on zbyt dobrze do synchronizacji zadań. Ale w połączeniu ze zmiennymi warunkowymi otrzymujesz bardzo potężne bloki konstrukcyjne do budowania wszelkiego rodzaju prymitywów ipc.

Więc moja rekomendacja jest taka: jeśli masz czysto zaimplementowane muteksy i zmienne warunkowe (jak w przypadku pthreadów POSIX), użyj ich.

Używaj semaforów tylko wtedy, gdy dokładnie pasują do problemu, który próbujesz rozwiązać, nie próbuj budować innych prymitywów (np. Rw-locks z semaforów, używaj do tego muteksów i zmiennych warunkowych)

Istnieje wiele nieporozumień muteksów i semaforów. Najlepsze wyjaśnienie, jakie do tej pory znalazłem, znajduje się w tym trzyczęściowym artykule:

Mutex kontra semafory - część 1: Semafory

Muteks kontra semafory - część 2: muteks

Mutex vs. semafory - część 3 (ostatnia część): problemy wzajemnego wykluczania


Adresy URL do tej witryny zawierają funky znaki i dlatego nie działają ... Pracuję nad tym
Peer Stritzinger

13

Chociaż odpowiedź @opaxdiablo jest całkowicie poprawna, chciałbym zwrócić uwagę, że scenariusz użycia obu rzeczy jest zupełnie inny. Mutex jest używany do ochrony części kodu przed równoczesnym działaniem, semafory są używane dla jednego wątku do sygnalizowania uruchomienia innego wątku.

/* 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

Scenariusz semafora jest inny:

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

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

Więcej informacji można znaleźć pod adresem http://www.netrino.com/node/202


2
Masz rację. Nawet jeśli używasz semafora z liczbą jeden, sugerujesz coś o tym, co robisz, niż gdybyś używał muteksu.
Omnifarious

Nie jestem pewien, czy się z tym zgadzam, chociaż nie zgadzam się tak gwałtownie, że przegłosuję Cię :-) Mówisz, że semafory są używane do powiadamiania wątków, ale to właśnie robią muteksy, gdy czeka kolejny wątek na nim i dokładnie to, czego nie robią semafory , gdy nie ma w nich wątków sema_wait:-) Moim zdaniem dotyczą zarówno zasobów, jak i powiadomień przekazywanych innym wątkom jest efektem ubocznym (bardzo ważnym pod względem wydajnościowym) ochrona.
paxdiablo

You say that the usage pattern of semaphores is to notify threadsJedna uwaga dotycząca powiadamiania wątków. Możesz bezpiecznie dzwonić sem_postz modułu obsługi sygnału ( pubs.opengroup.org/onlinepubs/009695399/functions/ ... ), ale nie zaleca się wywoływania pthread_mutex_locki pthread_mutex_unlockobsługi sygnału ( manpages.ubuntu.com/manpages/lucid/man3/… )

@paxdiablo: Jest jedna główna różnica między tym binarnym semaforem mutexa, polega na utrzymywaniu liczby odwołań. Mutex lub możesz powiedzieć, że dowolny warunkowy mutex nie zachowuje żadnej liczby związanej z blokadą, gdzie jako sempahore używaj do utrzymywania liczby. Tak więc sem_wait i sem_post utrzymują licznik.
Prak

9

Zobacz „Przykład toalety” - http://pheatt.emporia.edu/courses/2010/cs557f10/hand07/Mutex%20vs_%20Semaphore.htm :

Muteks:

To klucz do toalety. Jedna osoba może mieć klucz - zajmować toaletę - w tym czasie. Po zakończeniu osoba przekazuje (zwalnia) klucz kolejnej osobie w kolejce.

Oficjalnie: „Muteksy są zwykle używane do serializacji dostępu do sekcji kodu ponownie wchodzącego, którego nie można wykonać jednocześnie przez więcej niż jeden wątek. Obiekt mutex dopuszcza tylko jeden wątek do sekcji kontrolowanej, wymuszając na innych wątkach, które próbują uzyskać dostęp do tę sekcję, aby poczekać, aż pierwszy wątek wyjdzie z tej sekcji. " Ref: Biblioteka programistów Symbian

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

Semafor:

To liczba bezpłatnych identycznych kluczy do toalety. Przykład, powiedzmy, że mamy cztery toalety z identycznymi zamkami i kluczami. Liczba semaforów - liczba kluczy - jest ustawiona na 4 na początku (wszystkie cztery toalety są wolne), a następnie wartość zliczania jest zmniejszana w miarę wchodzenia ludzi. Jeśli wszystkie toalety są pełne, tj. nie ma wolnych kluczy, liczba semaforów wynosi 0. Teraz, gdy eq. jedna osoba wychodzi z toalety, semafor jest zwiększany do 1 (jeden darmowy 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 (zmniejszając wartość semafora) i mogą sygnalizować zakończenie korzystania z zasobu (zwiększanie semafora). " Ref: Biblioteka programistów Symbian


7

Staram się nie brzmieć szalenie, ale nie mogę się powstrzymać.

Twoje pytanie powinno brzmieć, jaka jest różnica między muteksem a semaforami? A dokładniej mówiąc, powinno brzmieć: „jaki jest związek między muteksem a semaforami?”

(Dodałbym to pytanie, ale jestem w stu procentach pewien, że jakiś nadgorliwy moderator zamknąłby je jako duplikat bez zrozumienia różnicy między różnicą a związkiem.)

W terminologii przedmiotowej możemy zauważyć, że:

obserwacja.1 Semafor zawiera muteks

obserwacja.2 Mutex nie jest semaforem, a semafor nie jest muteksem.

Istnieją semafory, które będą działać tak, jakby były muteksami, nazywane semaforami binarnymi, ale są one odlotowe, a NIE muteksowe.

Istnieje specjalny składnik o nazwie Signaling (posix używa zmiennej condition_variable dla tej nazwy), wymagany do utworzenia semafora z muteksu. Potraktuj to jako źródło powiadomień. Jeśli dwa lub więcej wątków subskrybuje to samo źródło powiadomień, można wysłać do nich wiadomość do JEDNEGO lub WSZYSTKICH w celu wybudzenia.

Może istnieć jeden lub więcej liczników powiązanych z semaforami, które są chronione przez muteks. Najprostszy scenariusz dla semafora, istnieje pojedynczy licznik, który może mieć wartość 0 lub 1.

To tutaj zamieszanie wlewa się jak deszcz monsunowy.

Semafor z licznikiem, który może mieć wartość 0 lub 1, NIE jest muteksem.

Mutex ma dwa stany (0,1) i jedną własność (zadanie). Semafor ma muteks, kilka liczników i zmienną warunkową.

Teraz użyj swojej wyobraźni, a każda kombinacja użycia licznika i kiedy sygnalizować może stworzyć jeden rodzaj semafora.

  1. Pojedynczy licznik o wartości 0 lub 1 i sygnalizacja, gdy wartość idzie do 1 ORAZ następnie odblokowuje jednego z gości oczekujących na sygnał == Semafor binarny

  2. Pojedynczy licznik z wartością od 0 do N i sygnalizujący, gdy wartość spadnie do mniej niż N i blokuje / czeka, gdy wartości są równe N == Semafor zliczający

  3. Pojedynczy licznik z wartością od 0 do N i sygnalizujący, gdy wartość idzie do N, i blokuje / czeka, gdy wartości są mniejsze niż N == Semafor barierowy (cóż, jeśli nie wywołują tego, to powinni.)

A teraz pytanie, kiedy czego użyć. (LUB raczej poprawne pytanie w wersji 3, kiedy używać muteksu, a kiedy semafora binarnego, ponieważ nie ma porównania z semaforem niebinarnym). Używaj muteksu, gdy 1. chcesz dostosować zachowanie, którego nie zapewnia binarny semafor, takie jak blokada spinowa, szybka blokada lub rekurencyjna blokada. Zwykle można dostosować muteksy za pomocą atrybutów, ale dostosowywanie semafora to nic innego jak napisanie nowego semafora. 2. chcesz lekki LUB szybszy prymityw

Używaj semaforów, gdy dokładnie to, czego chcesz, zapewnia.

Jeśli nie rozumiesz, co jest dostarczane przez twoją implementację semafora binarnego, to IMHO, użyj mutex.

I na koniec przeczytaj książkę, zamiast polegać tylko na SO.


5

Myślę, że pytanie powinno dotyczyć różnicy między muteksem a semaforem binarnym.

Mutex = Jest to mechanizm blokady własności, tylko wątek, który uzyska blokadę, może zwolnić blokadę.

binary Semaphore = Jest to bardziej mechanizm sygnałowy, każdy inny wątek o wyższym priorytecie może sygnalizować i przejmować blokadę.


5

Mutex ma chronić współdzielony zasób.
Semafor służy do wysyłania wątków.

Mutex:
Wyobraź sobie, że jest kilka biletów do sprzedania. Możemy zasymulować przypadek, w którym wiele osób kupuje bilety w tym samym czasie: każda osoba jest wątkiem do kupienia biletów. Oczywiście musimy użyć muteksu do ochrony biletów, ponieważ jest to zasób współdzielony.


Semafor:
Wyobraź sobie, że musimy wykonać poniższe obliczenia:

c = a + b;

Potrzebujemy również funkcji geta()do obliczania a, funkcji getb()do obliczania bi funkcji getc()do wykonywania obliczeń c = a + b.

Oczywiście nie możemy zrobić, c = a + bchyba że geta()i getb()skończyliśmy.
Jeśli te trzy funkcje są trzema wątkami, musimy wysłać trzy wątki.

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

Z pomocą semafora, powyższy kod może upewnić się, że t3nie wykona swojej pracy do czasu t1i t2wykonał swoją pracę.

Jednym słowem, semafor ma na celu wykonanie wątków w logicznej kolejności, podczas gdy mutex ma chronić współdzielone zasoby.
Więc NIE są tym samym, nawet jeśli niektórzy ludzie zawsze mówią, że mutex jest specjalnym semaforem o wartości początkowej 1. Możesz też tak powiedzieć, ale proszę zauważyć, że są one używane w różnych przypadkach. Nie zamieniaj jednego na drugie, nawet jeśli możesz to zrobić.


Sprzedaż biletów to fajny przykład. przykład semafora jest nieco niejasny (dla mnie zresztą).
prayagupd

1
@prayagupd Przykładem semafora jest tworzenie wątków w określonej kolejności, podczas gdy sprzedaż biletów nie wymaga żadnego zamówienia. Jeśli są trzy osoby: a, bi c. Kiedy przychodzą po bilety, w ogóle nie obchodzi nas kolejność kupowania. Jeśli jednak wykonamy takie obliczenie: z x = getx(); y = gety(); z = x + y;jakiegoś powodu używamy trzech wątków do zrobienia trzech rzeczy, teraz kolejność wątków jest bardzo ważna, ponieważ nie możemy tego zrobić, x + ychyba że getxi getyskończyliśmy. Jednym słowem semafor jest używany, gdy zależy nam na kolejności wykonywania wielowątkowości.
Yves

mam cię. Brzmi podobnie do bariery . Mogę powiedzieć, że poczekaj, aż wątki xi yzostaną zakończone, a następnie oblicz z = x + y. Wiem, że java ma CyclicBarrier. Nie jestem również pewien, czy mogę powiedzieć, że mapreducejest to przypadek użycia semafora, ponieważ nie mogę, reducedopóki wszystkie nie mapzostaną zakończone.
prayagupd

@prayagupd Yes. Możesz to powiedzieć.
Yves

2

Wszystkie powyższe odpowiedzi są dobrej jakości, ale ta jest tylko po to, aby ją zapamiętać. Nazwa Mutex wywodzi się od wzajemnie wykluczających się, stąd masz motywację do myślenia o blokadzie mutex jako o wzajemnym wykluczeniu między dwojgiem jako tylko jednym naraz, a jeśli ja posiadasz go możesz go mieć dopiero po zwolnieniu, z drugiej strony taki przypadek nie istnieje dla Semaphore jest jak sygnalizacja drogowa (co oznacza również słowo Semafor).


1

Jak już wspomniano, semafor z liczbą jeden to to samo, co semafor „binarny”, czyli to samo co muteks.

Głównymi rzeczami, które widziałem, są semafory o liczbie większej niż jeden używany do tego, że istnieje sytuacja producenta / konsumenta, w której masz kolejkę o określonym ustalonym rozmiarze.

Masz więc dwa semafory. Pierwszy semafor jest początkowo ustawiony na liczbę elementów w kolejce, a drugi semafor jest ustawiony na 0. Producent wykonuje operację P na pierwszym semaforze i dodaje do kolejki. i wykonuje operację V na sekundę. Konsument wykonuje operację P na drugim semaforze, usuwa z kolejki, a następnie wykonuje operację V na pierwszym semaforze.

W ten sposób producent jest blokowany za każdym razem, gdy wypełnia kolejkę, a konsument jest blokowany, gdy kolejka jest pusta.


1

Muteks to szczególny przypadek semafora. Semafor umożliwia przejście kilku wątków do sekcji krytycznej. Podczas tworzenia semafora definiujesz, w jaki sposób wątki mogą być dozwolone w sekcji krytycznej. Oczywiście Twój kod musi obsługiwać kilka dostępów do tej krytycznej sekcji.


-1

Semafor binarny i muteks są różne. Z punktu widzenia systemu operacyjnego semafor binarny i semafor zliczający są implementowane w ten sam sposób, a semafor binarny może mieć wartość 0 lub 1.

Mutex -> Może być używany tylko do jednego i jedynego celu wzajemnego wykluczania krytycznej sekcji kodu.

Semafor -> Może być używany do rozwiązywania różnych problemów. Binarny semafor może służyć do sygnalizacji, a także rozwiązywania problemu wzajemnego wykluczania. Po zainicjowaniu na 0 rozwiązuje problem sygnalizacji, a po zainicjowaniu na 1 rozwiązuje problem wzajemnego wykluczania .

Gdy ilość zasobów jest większa i wymaga synchronizacji, możemy użyć semafora zliczającego.

Na swoim blogu szczegółowo omówiłem te tematy.

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

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.