Semafor to koncepcja programowania, która jest często używana do rozwiązywania problemów związanych z wielowątkowością. Moje pytanie do społeczności:
Co to jest semafor i jak go używasz?
multithreading
concurrency
semaphore
bmurphy1976
źródło
źródło
Odpowiedzi:
Pomyśl o semaforach jako bramkarzach w nocnym klubie. Istnieje specjalna liczba osób, które mogą przebywać w klubie jednocześnie. Jeśli klub jest pełny, nikt nie może wejść, ale jak tylko jedna osoba opuści inną osobę, może wejść.
Jest to po prostu sposób na ograniczenie liczby konsumentów dla określonego zasobu. Na przykład, aby ograniczyć liczbę jednoczesnych wywołań do bazy danych w aplikacji.
Oto bardzo pedagogiczny przykład w C # :-)
źródło
Artykuł Mutexes and Semaphores Demystified by Michael Barr jest doskonałym krótkim wprowadzeniem do tego, co odróżnia muteksy i semafory od tego, kiedy i kiedy powinny i nie powinny być używane. Fragment kilku kluczowych akapitów tutaj.
Kluczową kwestią jest to, że do ochrony wspólnych zasobów należy używać muteksów, a do sygnalizowania należy używać semaforów. Zasadniczo nie należy używać semaforów do ochrony wspólnych zasobów ani muteksów do sygnalizowania. Istnieją na przykład problemy z analogią bouncera pod względem używania semaforów do ochrony współdzielonych zasobów - możesz z nich korzystać w ten sposób, ale może to utrudniać zdiagnozowanie błędów.
...
W tym miejscu powstaje interesująca analogia, wykorzystująca ideę kluczy do łazienki jako ochrony wspólnych zasobów - łazienki. Jeśli sklep ma jedną łazienkę, wystarczy jeden klucz, aby chronić ten zasób i uniemożliwić korzystanie z niego wielu osobom jednocześnie.
Jeśli jest wiele łazienek, można pokusić się o ich równe wprowadzenie i zrobienie wielu kluczy - jest to podobne do niewłaściwego użycia semafora. Kiedy już zdobędziesz klucz, nie wiesz, która łazienka jest dostępna, a jeśli pójdziesz tą ścieżką, prawdopodobnie skończysz z użyciem muteksów, aby dostarczyć te informacje i upewnić się, że nie weźmiesz łazienki, która jest już zajęta. .
Semafor jest niewłaściwym narzędziem do ochrony kilku zasadniczo takich samych zasobów, ale tyle osób o nim myśli i używa go. Analogia bramkarza jest wyraźnie inna - nie ma kilku zasobów tego samego typu, zamiast tego istnieje jeden zasób, który może przyjąć wielu użytkowników jednocześnie. Przypuszczam, że w takich sytuacjach można zastosować semafor, ale rzadko zdarzają się sytuacje w świecie rzeczywistym, w których analogia faktycznie się utrzymuje - częściej występuje kilka tego samego typu, ale wciąż pojedyncze zasoby, takie jak łazienki, których nie można użyć tą drogą.
...
...
Tutaj ważna jest uwaga, że muteksy źle wpływają na systemy operacyjne w czasie rzeczywistym, powodując odwrócenie priorytetu w przypadku, gdy mniej ważne zadanie może zostać wykonane przed ważniejszym zadaniem z powodu współdzielenia zasobów. Krótko mówiąc, dzieje się tak, gdy zadanie o niższym priorytecie wykorzystuje muteks do pobrania zasobu A, a następnie próbuje złapać B, ale zostaje wstrzymany, ponieważ B jest niedostępny. W trakcie oczekiwania pojawia się zadanie o wyższym priorytecie, które potrzebuje A, ale jest już powiązane i przez proces, który nawet nie działa, ponieważ czeka na B. Istnieje wiele sposobów rozwiązania tego problemu, ale najczęściej jest to naprawione zmieniając mutex i menedżera zadań. Muteks jest w tych przypadkach znacznie bardziej złożony niż semafor binarny,
...
Mutex: udostępnianie zasobów
Semafor: sygnalizacja
Nie używaj jednego do drugiego bez dokładnego rozważenia skutków ubocznych.
źródło
Mutex: wyłączny dostęp członka do zasobu
Semafor: dostęp n-członka do zasobu
Oznacza to, że mutex może być używany do synchronizacji dostępu do licznika, pliku, bazy danych itp.
Sempahore może robić to samo, ale obsługuje stałą liczbę jednoczesnych rozmówców. Na przykład mogę zawinąć wywołania bazy danych w semafor (3), aby moja aplikacja wielowątkowa trafiła do bazy danych z maksymalnie 3 jednoczesnymi połączeniami. Wszystkie próby zostaną zablokowane, dopóki nie otworzy się jedno z trzech miejsc. Sprawiają, że wykonywanie naiwnego dławienia jest naprawdę bardzo łatwe.
źródło
Rozważ taksówkę, która może pomieścić łącznie 3 (z tyłu ) +2 (z przodu ) osób, w tym kierowcę. A zatem,
semaphore
pozwala tylko 5 osobom w samochodzie na raz. Imutex
pozwala tylko 1 osobie na jednym siedzeniu samochodu.Dlatego
Mutex
ma umożliwić wyłączny dostęp do zasobu ( takiego jak wątek systemu operacyjnego ), podczas gdy aSemaphore
ma umożliwić dostęp dla n liczby zasobów jednocześnie.źródło
@Craig:
Nie jest to ograniczone tylko do jednego wątku. Semafor można skonfigurować tak, aby zezwalał na dostęp do zasobu określonej liczbie wątków.
źródło
Semafor może być również użyty jako ... semafor. Na przykład, jeśli masz wiele procesów kolejkujących dane do kolejki i tylko jedno zadanie zużywa dane z kolejki. Jeśli nie chcesz, aby Twoje zadanie konsumenckie stale odpytywało kolejkę w poszukiwaniu dostępnych danych, możesz użyć semafora.
W tym przypadku semafor nie jest wykorzystywany jako mechanizm wykluczający, ale jako mechanizm sygnalizacyjny. Zadanie konsumujące czeka na semaforze Zadanie produkcyjne publikuje w semaforze.
W ten sposób zadanie konsumujące jest uruchamiane tylko wtedy, gdy istnieją dane do usunięcia z kolejki
źródło
Istnieją dwie podstawowe koncepcje budowy współbieżnych programów - synchronizacja i wzajemne wykluczanie. Zobaczymy, jak te dwa rodzaje zamków (semafory są bardziej rodzajem mechanizmu blokującego) pomagają nam osiągnąć synchronizację i wzajemne wykluczenie.
Semafor jest konstrukcją programistyczną, która pomaga nam osiągnąć współbieżność, realizując zarówno synchronizację, jak i wzajemne wykluczanie. Semafory są dwojakiego rodzaju, binarne i zliczające.
Semafor składa się z dwóch części: licznika i listy zadań oczekujących na dostęp do określonego zasobu. Semafor wykonuje dwie operacje: poczekaj (P) [to jak uzyskanie blokady] i zwolnij (V) [podobnie do zwolnienia blokady] - są to jedyne dwie operacje, które można wykonać na semaforze. W semaforze binarnym licznik logicznie przechodzi między 0 a 1. Można go uznać za podobny do zamka z dwiema wartościami: otwarta / zamknięta. Semafor zliczający ma wiele wartości dla zliczania.
Ważne jest, aby zrozumieć, że licznik semaforów śledzi liczbę zadań, które nie muszą być blokowane, tzn. Mogą robić postępy. Zadania blokują się i dodają się do listy semaforów tylko wtedy, gdy licznik wynosi zero. Dlatego zadanie jest dodawane do listy w procedurze P (), jeśli nie może się rozwijać, i „uwalniane” za pomocą procedury V ().
Teraz dość oczywiste jest, jak semafory binarne można wykorzystać do rozwiązania synchronizacji i wzajemnego wykluczenia - są to zasadniczo blokady.
dawny. Synchronizacja:
W powyższym przykładzie B2 może wykonać się dopiero po zakończeniu wykonywania B1. Powiedzmy, że wątek A przychodzi jako pierwszy - przechodzi do sem.P () i czeka, ponieważ licznik ma wartość 0 (zamknięty). Nadchodzi wątek B, kończy B1, a następnie uwalnia wątek A - który następnie kończy B2. Osiągamy synchronizację.
Spójrzmy teraz na wzajemne wykluczanie za pomocą binarnego semafora:
Wzajemne wykluczenie jest również dość proste - m1 i m2 nie mogą jednocześnie wejść do sekcji krytycznej. Tak więc każdy wątek używa tego samego semafora, aby zapewnić wzajemne wykluczenie dla swoich dwóch krytycznych sekcji. Czy można mieć większą współbieżność? Zależy od najważniejszych sekcji. (Pomyśl, jak inaczej można użyć semaforów, aby osiągnąć wzajemne wykluczenie. Wskazówka: czy koniecznie muszę używać tylko jednego semafora?)
Liczenie semaforów: semafor z więcej niż jedną wartością. Spójrzmy na to, co to oznacza - zamek z więcej niż jedną wartością? Tak otwarte, zamknięte i ... hmm. Jaki jest pożytek z blokady wielostopniowej we wzajemnym wykluczaniu lub synchronizacji?
Weźmy łatwiejszy z dwóch:
Synchronizacja z wykorzystaniem semafora zliczającego: Załóżmy, że masz 3 zadania - nr 1 i 2, które chcesz wykonać po 3. Jak zaprojektowałbyś swoją synchronizację?
Więc jeśli semafor zaczyna się zamknięty, upewniasz się, że t1 i t2 blokują, dodawane są do listy semaforów. Potem pojawia się wszystkie ważne t3, kończy swój biznes i uwalnia t1 i t2. W jakiej kolejności są uwalniane? Zależy od implementacji listy semaforów. Może to być FIFO, może mieć określony priorytet itp. (Uwaga: pomyśl o tym, jak ułożysz P i V; s, jeśli chcesz, aby t1 i t2 były wykonywane w określonej kolejności i jeśli nie byłeś świadomy implementacji semafora)
(Dowiedz się: co się stanie, jeśli liczba V jest większa niż liczba P?)
Wzajemne wykluczanie Korzystanie z liczenia semaforów: Chciałbym, abyś skonstruował w tym celu swój własny pseudokod (sprawia, że rozumiesz lepiej!) - ale podstawowa koncepcja jest taka: semafor liczenia licznika = N pozwala N zadań swobodnie wchodzić do sekcji krytycznej . Oznacza to, że masz N zadań (lub wątków, jeśli chcesz), wchodzisz do sekcji krytycznej, ale zadanie N + 1 zostaje zablokowane (przechodzi na naszą ulubioną listę zablokowanych zadań) i jest przepuszczane tylko wtedy, gdy ktoś V jest semaforem przynajmniej raz. Licznik semaforów zamiast wahać się między 0 a 1, teraz przechodzi między 0 i N, umożliwiając N zadaniom swobodne wchodzenie i wychodzenie, nie blokując nikogo!
O rany, dlaczego miałbyś potrzebować tak głupiej rzeczy? Czy nie chodzi o to, by wzajemne wykluczenie nie pozwalało więcej niż jednemu facetowi na dostęp do zasobów? (Wskazówka Wskazówka ... Nie zawsze masz tylko jeden dysk w komputerze, prawda ...?)
Do przemyślenia : Czy wzajemne wykluczenie osiąga się, mając sam liczący semafor? Co się stanie, jeśli masz 10 instancji zasobu, a 10 wątków wchodzi (przez semafor zliczający) i próbujesz użyć pierwszej instancji?
źródło
Semafor to obiekt zawierający liczbę naturalną (tj. Liczbę całkowitą większą lub równą zero), na której zdefiniowane są dwie operacje modyfikujące. Jedna operacja
V
dodaje 1 do naturalnego. Druga operacjaP
zmniejsza liczbę naturalną o 1. Obie czynności są atomowe (tzn. Żadna inna operacja nie może być wykonana w tym samym czasie co aV
lub aP
).Ponieważ liczby naturalnej 0 nie można zmniejszyć, wywołanie
P
semafora zawierającego 0 zablokuje wykonanie procesu wywołującego (/ wątku) do momentu, w którym liczba nie będzie już równa 0 iP
będzie mogła zostać pomyślnie (i atomowo) wykonana.Jak wspomniano w innych odpowiedziach, semaforów można użyć do ograniczenia dostępu do określonego zasobu do maksymalnej (ale zmiennej) liczby procesów.
źródło
Stworzyłem wizualizację, która powinna pomóc w zrozumieniu pomysłu. Semafor kontroluje dostęp do wspólnego zasobu w środowisku wielowątkowym.
Wynik
Przykładowy kod z artykułu
źródło
Flaga sprzętu lub oprogramowania. W systemach wielozadaniowych semafor jest tak zmienny, że ma wartość wskazującą status wspólnego zasobu. Proces wymagający zasobu sprawdza semafor, aby określić status zasobów, a następnie decyduje, jak postępować.
źródło
Semafory działają jak ograniczniki wątków.
Przykład: Jeśli masz pulę 100 wątków i chcesz wykonać operację DB. Jeśli 100 wątków uzyskuje dostęp do DB w danym momencie, może wystąpić problem z blokowaniem w DB, więc możemy użyć semafora, który dopuszcza tylko ograniczony wątek naraz. Poniżej Przykład dopuszcza tylko jeden wątek na raz. Gdy wątek
acquire()
wywoła metodę, uzyska dostęp, a po wywołaniurelease()
metody zwolni dostęp, aby następny wątek uzyskał dostęp.źródło
Wyobraź sobie, że wszyscy próbują iść do łazienki, a do łazienki jest tylko pewna liczba kluczy. Teraz, jeśli nie ma wystarczającej liczby kluczy, ta osoba musi poczekać. Pomyśl więc o semaforze, który reprezentuje zestaw kluczy dostępnych dla łazienek (zasobów systemowych), do których różne procesy (osoby korzystające z łazienki) mogą poprosić o dostęp.
Teraz wyobraź sobie dwa procesy próbujące iść do łazienki w tym samym czasie. To nie jest dobra sytuacja, a semafory są używane, aby temu zapobiec. Niestety semafor jest mechanizmem dobrowolnym i procesy (nasi użytkownicy w łazience) mogą go zignorować (tzn. Nawet jeśli są klucze, ktoś może po prostu otworzyć drzwi).
Istnieją również różnice między semaforami binarnymi / muteksowymi i liczącymi.
Sprawdź notatki z wykładów na stronie http://www.cs.columbia.edu/~jae/4118/lect/L05-ipc.html .
źródło
To stare pytanie, ale jednym z najciekawszych zastosowań semaforów jest blokada odczytu / zapisu i nie została wyraźnie wymieniona.
Blokady r / w działają w prosty sposób: zużywają jedno pozwolenie dla czytelnika i wszystkie pozwolenia dla pisarzy. Rzeczywiście, trywialna implementacja blokady ar / w, ale wymaga modyfikacji metadanych podczas odczytu (właściwie dwa razy), która może stać się wąskim gardłem, wciąż znacznie lepszym niż mutex lub blokada.
Inną wadą jest to, że pisarze mogą być również uruchamiani dość łatwo, chyba że semafor jest sprawiedliwy lub zapisy uzyskują zezwolenia na wiele żądań, w takim przypadku potrzebują jawnego muteksu między sobą.
Czytaj dalej :
źródło
Semafor to sposób na zablokowanie zasobu, aby zagwarantować, że podczas wykonywania fragmentu kodu tylko ten fragment ma dostęp do tego zasobu. Dzięki temu dwa wątki nie będą jednocześnie uzyskiwać dostępu do zasobu, co może powodować problemy.
źródło