Czy jest jakaś różnica między binarnym semaforem a muteksem, czy są one zasadniczo takie same?
Czy jest jakaś różnica między binarnym semaforem a muteksem, czy są one zasadniczo takie same?
Odpowiedzi:
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:
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.
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.
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
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
Ł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.
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 .
Ich semantyka synchronizacji jest bardzo różna:
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ć).
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.
futex
istnieje 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.
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.
Mutex: Załóżmy, że mamy wątek sekcji krytycznej T1 chce uzyskać do niego dostęp, a następnie wykonuje poniższe kroki. T1:
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:
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.
W systemie Windows istnieją dwie różnice między muteksami a semaforami binarnymi:
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.
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.
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ą !,
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”.
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ć”
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
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.
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.
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.
Mutex pracuje nad blokowaniem krytycznego regionu, ale Semafor działa na zasadzie liczenia.
http://www.geeksforgeeks.org/archives/9102 szczegółowo omawia.
Mutex
to mechanizm blokujący używany do synchronizacji dostępu do zasobu.
Semaphore
jest mechanizmem sygnalizacyjnym.
Od programisty zależy, czy zamiast muteksu chce użyć semafora binarnego.
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.
sem_post()
dla SCHED_FIFO
iSCHED_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ć.
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.
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:
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, EDEADLK
jeśli spróbujesz dwa razy to samo zablokować i EPERM
odblokujesz 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");
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.
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.
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 .
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.
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ć .
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.
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.
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] Linux Kernel Development, trzecia edycja Robert Love
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.