Udostępnij za pośrednictwem


Semaphore i SemaphoreSlim

Klasa System.Threading.Semaphore reprezentuje semafor nazwany, zarówno systemowy, jak i lokalny. Jest to cienka powłoka wokół obiektu semafora Win32. Semafory liczące Win32 to semafory, które można używać 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 semaforów ani użycia uchwytu oczekiwania do synchronizacji.

Zarządzanie ograniczonym zasobem

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

Wątek może wielokrotnie wejść do semafora, wywołując metodę obiektu System.Threading.Semaphore lub metodę obiektu WaitOne wielokrotnie. Aby zwolnić semafor, wątek może wywołać przeciążoną metodę Semaphore.Release() lub SemaphoreSlim.Release() określoną liczbę razy lub wywołać przeciążenie metody Semaphore.Release(Int32) lub SemaphoreSlim.Release(Int32) i określić liczbę wpisów do zwolnienia.

Semafory i identyfikacja 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 semaforów obejmuje wątek producenta i wątek konsumenta, gdzie jeden wątek zawsze zwiększa liczbę semafora, a drugi ją zmniejsza.

Programista powinien zadbać, aby wątek nie zwalniał semafora zbyt często. Załóżmy na przykład, że semafor ma maksymalną wartość dwa i że zarówno wątek A, jak i wątek B wchodzą do semafora. Jeśli błąd programowania w wątku B powoduje dwukrotne wywołanie Release , oba wywołania kończą się powodzeniem. Licznik semafora jest pełny, a gdy wątek A ostatecznie wywołuje Release, SemaphoreFullException jest wyrzucany.

Nazwane semafory

System operacyjny Windows umożliwia semaforom posiadanie nazw. Nazwany semafor jest w całym systemie. Oznacza to, że po utworzeniu nazwanego semafora jest on dostępny dla wszystkich wątków w ramach wszystkich procesów. 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 / Notatka

Ponieważ nazwane semafory są rozpoznawalne przez cały system, istnieje możliwość utworzenia wielu Semaphore obiektów reprezentujących ten sam nazwany 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 semaforów. Ponieważ obejmują cały system, inny proces, który używa tej samej nazwy, może nieoczekiwanie wprowadzić się do semafora. 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 metody Semaphore.SetAccessControl, ale powoduje to pozostawienie okna zagrożenia między utworzeniem semafora a momentem jego zabezpieczenia. 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 także