Semafor i klasa SemaphoreSlim

Klasa System.Threading.Semaphore reprezentuje nazwany (systemwide) lub semafor lokalny. Jest to cienka otoka wokół obiektu semafora Win32. Win32 semaphores liczą semafory, które mogą służyć do kontrolowania dostępu do puli zasobów.

Klasa SemaphoreSlim reprezentuje lekki, szybki semafor, który może być używany do oczekiwania w ramach jednego procesu, gdy oczekuje się, że czas oczekiwania będzie bardzo krótki. SemaphoreSlim opiera się jak najwięcej na elementach pierwotnych synchronizacji udostępnianych przez środowisko uruchomieniowe języka wspólnego (CLR). Jednak zapewnia również leniwie zainicjowane, oparte na jądrze uchwyty oczekiwania zgodnie z potrzebami, aby obsługiwać oczekiwanie na wiele semaforów. SemaphoreSlim Obsługuje również korzystanie z tokenów anulowania, ale nie obsługuje nazwanych semaphores ani użycia uchwytu oczekiwania na synchronizację.

Zarządzanie ograniczonym zasobem

Wątki wprowadzają semafor, wywołując WaitOne metodę, która jest dziedziczona z WaitHandle klasy, w przypadku System.Threading.Semaphore obiektu lub SemaphoreSlim.Wait metody w przypadku obiektu lub SemaphoreSlim.WaitAsync w przypadku SemaphoreSlim obiektu . Po powrocie wywołania liczba semaforów jest dekrementowana. Gdy wątek żąda wpisu i liczba jest równa zero, bloki wątku. W miarę jak wątki zwalniają semafor przez wywołanie Semaphore.Release metody lub SemaphoreSlim.Release , zablokowane wątki mogą wprowadzać. Nie ma gwarantowanej kolejności, takiej jak first-in, first-out (FIFO) lub last-in, first-out (LIFO), dla zablokowanych wątków do wejścia semafora.

Wątek może wielokrotnie wprowadzać semafor, wywołując System.Threading.Semaphore metodę obiektu lub SemaphoreSlim metodę obiektu WaitOneWait wielokrotnie. Aby zwolnić semafor, wątek może wywołać Semaphore.Release() metodę lub SemaphoreSlim.Release() przeciążyć tę samą liczbę razy lub wywołać Semaphore.Release(Int32) przeciążenie metody or SemaphoreSlim.Release(Int32) i określić liczbę wpisów do wydania.

Semaphores i tożsamość wątku

Dwa typy semaforów nie wymuszają tożsamości wątku na wywołaniach metod WaitOne, Wait, Releasei SemaphoreSlim.Release . Na przykład typowy scenariusz użycia dla semaforów obejmuje wątki producenta i wątku konsumenta, z jednym wątkiem zawsze zwiększającym liczbę semaforów i drugą zawsze ją dekrementując.

Obowiązkiem programisty jest zapewnienie, że wątek nie zwalnia semafora zbyt wiele razy. Załóżmy na przykład, że semafor ma maksymalną liczbę dwóch, a ten wątek A i wątek B wprowadzają semafor. Jeśli błąd programowania w wątku B powoduje dwukrotne wywołanie Release , oba wywołania kończą się powodzeniem. Liczba semaforów jest pełna, a gdy wątek A ostatecznie wywołuje Releaseelement , SemaphoreFullException jest zgłaszany.

Nazwane Semaphores

System operacyjny Windows umożliwia semaforom posiadanie nazw. Nazwany semafor jest szeroki system. Oznacza to, że po utworzeniu nazwanego semafora jest on widoczny dla wszystkich wątków we wszystkich procesach. W związku z tym nazwany semafor może służyć do synchronizowania działań procesów, a także wątków.

Można utworzyć Semaphore obiekt reprezentujący nazwany semafor systemowy przy użyciu jednego z konstruktorów, który określa nazwę.

Uwaga

Ponieważ nazwane semafory są szeroko dostępne, istnieje możliwość posiadania wielu Semaphore obiektów reprezentujących ten sam semafor o nazwie semafor. Za każdym razem, gdy wywołujesz konstruktor lub Semaphore.OpenExisting metodę, tworzony jest nowy Semaphore obiekt. Określenie tej samej nazwy wielokrotnie tworzy wiele obiektów reprezentujących ten sam semaphor.

Zachowaj ostrożność podczas używania nazwanych semaphores. Ponieważ są one szerokie, inny proces, który używa tej samej nazwy, może nieoczekiwanie wprowadzić semafor. Złośliwy kod wykonywany na tym samym komputerze może użyć go jako podstawy ataku typu "odmowa usługi".

Użyj zabezpieczeń kontroli dostępu, aby chronić Semaphore obiekt reprezentujący nazwany semafor, najlepiej przy użyciu konstruktora, który określa System.Security.AccessControl.SemaphoreSecurity obiekt. Można również zastosować zabezpieczenia kontroli dostępu przy użyciu Semaphore.SetAccessControl metody , ale powoduje to pozostawienie okna luki w zabezpieczeniach między utworzeniem semafora a czasem jego ochrony. Ochrona semaforów przy użyciu zabezpieczeń kontroli dostępu pomaga zapobiegać złośliwym atakom, ale nie rozwiązuje problemu niezamierzonych kolizji nazw.

Zobacz też