Odpowiedzi:
Semafor można policzyć, podczas gdy muteks może liczyć tylko do 1.
Załóżmy, że masz uruchomiony wątek, który akceptuje połączenia klientów. Ten wątek może obsługiwać 10 klientów jednocześnie. Następnie każdy nowy klient ustawia semafor, aż osiągnie 10. Kiedy semafor ma 10 flag, twój wątek nie będzie akceptował nowych połączeń
Muteksy są zwykle używane do ochrony rzeczy. Załóżmy, że 10 klientów ma dostęp do wielu części systemu. Następnie możesz zabezpieczyć część systemu za pomocą muteksu, więc gdy 1 klient jest podłączony do tego podsystemu, nikt inny nie powinien mieć dostępu. Do tego celu możesz również użyć semafora. Muteks to „Semafor wzajemnego wykluczenia” .
ReentrantLock
. Wszystkie te są rekurencyjne. Nie znam żadnych przykładów nierekurencyjnych muteksów z „prawdziwego świata” (widziałem je tylko w podręcznikach), więc ich nie rozważałem.
Niestety wszyscy przeoczyli najważniejszą różnicę między semaforem a muteksem; pojęcie „ własności ”.
Semafory nie mają pojęcia własności, co oznacza, że każdy wątek może zwolnić semafor (może to prowadzić do wielu problemów samo w sobie, ale może pomóc w „wykrywaniu śmierci”). Podczas gdy mutex ma pojęcie własności (tj. Możesz zwolnić mutex, który nabyłeś).
Własność jest niezwykle ważna dla bezpiecznego programowania systemów współbieżnych. Zawsze zalecałbym używanie muteksu zamiast semafora (ale ma to wpływ na wydajność).
Muteksy mogą również obsługiwać dziedziczenie priorytetów (co może pomóc w rozwiązaniu problemu inwersji priorytetów) i rekursję (eliminując jeden typ zakleszczenia).
Należy również podkreślić, że istnieją semafory „binarne” i semafory „liczące / ogólne”. Semafor Javy jest semaforem zliczającym, dzięki czemu można go zainicjować wartością większą niż jeden (podczas gdy, jak wskazano, muteks może liczyć tylko jeden). Na przydatność tego wskazano w innych postach.
Podsumowując, jeśli nie masz wielu zasobów do zarządzania, zawsze zalecałbym muteks zamiast semafora.
Mutex to w zasadzie wzajemne wykluczenie. Tylko jeden wątek może uzyskać zasób na raz. Gdy jeden wątek pozyskuje zasób, żaden inny wątek nie może uzyskać zasobu, dopóki wątek będący właścicielem zasobu nie zostanie zwolniony. Wszystkie wątki oczekujące na pozyskanie zasobu zostałyby zablokowane.
Semafor służy do kontrolowania liczby wykonywanych wątków. Będzie ustalony zestaw zasobów. Liczba zasobów zostanie zmniejszona za każdym razem, gdy wątek jest właścicielem tego samego. Gdy liczba semaforów osiągnie 0, żadne inne wątki nie mogą uzyskać zasobu. Wątki są blokowane do czasu, gdy inne wątki są właścicielami wydania zasobów.
Krótko mówiąc, główna różnica polega na tym, ile wątków może jednocześnie uzyskać zasób?
Mutex służy do szeregowego dostępu do zasobu, podczas gdy semafor ogranicza dostęp do zasobu do określonej liczby. Możesz myśleć o muteksie jak o semaforze z liczbą dostępu równą 1. Niezależnie od ustawienia licznika semaforów, wątki mogą uzyskać dostęp do zasobu, zanim zasób zostanie zablokowany.
Semafor jest liczącym mechanizmem synchronizacji, a muteks nie.
Na to pytanie można znaleźć odpowiednie odpowiedzi i łącze do oficjalnych wskazówek dotyczących języka Java: Czy w Javie istnieje muteks?
Semafor :
Semafor liczący. Koncepcyjnie semafor zachowuje zestaw zezwoleń. Każdy
acquire()
blokuje się, jeśli to konieczne, aż do uzyskania zezwolenia, a następnie je przyjmuje. Każdyrelease()
dodaje zezwolenie, potencjalnie zwalniając blokującego nabywcę. Jednak żadne rzeczywiste obiekty zezwoleń nie są używane; Semafor po prostu liczy dostępną liczbę i działa odpowiednio.
Semafory są często używane w celu ograniczenia liczby wątków, które mogą uzyskać dostęp do niektórych (fizycznych lub logicznych) zasobów
Java nie ma wbudowanego interfejsu API Mutex. Ale można go zaimplementować jako semafor binarny.
Semafor zainicjowany na jeden semafor, który jest używany w taki sposób, że ma co najwyżej jedno dostępne zezwolenie, może służyć jako blokada wzajemnego wykluczania. Jest to bardziej powszechnie znane jako semafor binarny, ponieważ ma tylko dwa stany: jedno dostępne zezwolenie lub zero dostępnych zezwoleń.
Użyty w ten sposób semafor binarny ma tę właściwość (w przeciwieństwie do wielu implementacji Lock), że "blokada" może zostać zwolniona przez wątek inny niż właściciel (ponieważ semafory nie mają pojęcia własności) . Może to być przydatne w niektórych specjalistycznych kontekstach, takich jak odzyskiwanie zakleszczenia.
A więc kluczowe różnice między Semaphore i Mutex:
Semafor ogranicza liczbę wątków, aby uzyskać dostęp do zasobu za pośrednictwem zezwoleń. Mutex pozwala tylko jednemu wątkowi na dostęp do zasobów.
Żaden wątek nie jest właścicielem Semaphore. Wątki mogą aktualizować liczbę zezwoleń przez wywołanie acquire()
i release()
metody. Muteksy należy odblokowywać tylko za pomocą nici przytrzymującej zamek.
Kiedy mutex jest używany ze zmiennymi warunkowymi, istnieje domniemany nawias - jest jasne, która część programu jest chroniona . Niekoniecznie tak jest w przypadku semafora, który można by nazwać przejściem do programowania współbieżnego - jest potężny, ale zbyt łatwy w użyciu w nieustrukturyzowany, nieokreślony sposób.
Mutex to semafor binarny. Musi być zainicjowany wartością 1, aby spełniona była zasada „kto pierwszy, ten lepszy”. To prowadzi nas do innego specjalnego własności każdego mutex: kto nie w dół , musi być tym, który robi się . W efekcie uzyskaliśmy wzajemne wykluczenie jakiegoś zasobu.
Teraz możesz zobaczyć, że mutex jest specjalnym przypadkiem semafora ogólnego.
Przedmiot synchronizacji Semaforrealizuje klasyczną sygnalizację świetlną. Sygnalizacja świetlna kontroluje dostęp do zasobu współdzielonego przez licznik. Jeśli licznik jest większy niż zero, przyznawany jest dostęp; Jeśli wynosi zero, odmowa dostępu. Licznik zlicza uprawnienia, które umożliwiają dostęp do udostępnionego zasobu. Następnie, aby uzyskać dostęp do zasobu, wątek musi otrzymać pozwolenie od sygnalizacji świetlnej. Ogólnie rzecz biorąc, aby użyć sygnalizacji świetlnej, wątek, który chce uzyskać dostęp do udostępnionego zasobu, próbuje uzyskać zezwolenie. Jeśli liczba sygnalizacji świetlnej jest większa od zera, wątek uzyskuje zezwolenie, a liczba sygnalizacji świetlnej jest zmniejszana. W przeciwnym razie wątek zostanie zablokowany do czasu uzyskania pozwolenia. Gdy wątek nie potrzebuje już dostępu do udostępnionego zasobu, zwalnia pozwolenie, więc liczba sygnalizacji świetlnej wzrasta. Jeśli jest inny wątek czekający na zezwolenie, uzyska wtedy zezwolenie. Klasa Semaphore w Javie implementuje ten mechanizm.
Semafor ma dwóch konstruktorów:
Semaphore(int num)
Semaphore(int num, boolean come)
num określa początkową liczbę zezwoleń. Następnie num określa liczbę wątków, które mogą uzyskać dostęp do udostępnionego zasobu w danym momencie. Jeśli num to jeden, może uzyskać dostęp do zasobu po jednym wątku naraz. Przez ustawienie się jak prawdziwy, można zagwarantować, że nici czekasz na pozwolenie są w kolejności ich wniosek.
Porównujesz niezrównane, technicznie nie ma różnicy między Semaforem a muteksem, to nie ma sensu. Mutex to po prostu znacząca nazwa, jak każda inna nazwa w logice aplikacji, oznacza to, że inicjalizujesz semafor na "1", jest on używany ogólnie do ochrony zasobu lub chronionej zmiennej w celu zapewnienia wzajemnego wykluczenia.