Delen via


Semaphore en SemaphoreSlim

De System.Threading.Semaphore klasse vertegenwoordigt een benoemde (systeemomvattende) of lokale semafore. Het is een dunne wrapper rond het Win32-semaphore-object. Win32-semaforen zijn tellende semaforen, die kunnen worden gebruikt om de toegang tot een pool van resources te beheren.

De SemaphoreSlim klasse vertegenwoordigt een lichtgewicht, snelle semafore die kan worden gebruikt voor het wachten binnen één proces wanneer de wachttijden naar verwachting zeer kort zijn. SemaphoreSlim is zoveel mogelijk afhankelijk van synchronisatie primitiefen die worden geleverd door de Common Language Runtime (CLR). Het biedt echter ook vertraagd geïnitialiseerde wachtgrepen op basis van kernel indien nodig ter ondersteuning van het wachten op meerdere semaphores. SemaphoreSlim ondersteunt ook het gebruik van annuleertokens, maar biedt geen ondersteuning voor genaamde semafoors of het gebruik van een wachtgreep voor synchronisatie.

Een beperkte resource beheren

nl-NL: Threads gaan de semafoor binnen door de WaitOne-methode aan te roepen, die wordt overgenomen van de WaitHandle-klasse, in het geval van een System.Threading.Semaphore-object, of de SemaphoreSlim.Wait- of SemaphoreSlim.WaitAsync-methode, in het geval van een SemaphoreSlim-object. Wanneer de aanroep terugkeert, wordt de telling van de semafoor verminderd. Wanneer een thread invoer aanvraagt en het aantal nul is, blokkeert de thread. Wanneer threads de semaphore vrijgeven door de Semaphore.Release of SemaphoreSlim.Release methode aan te roepen, kunnen geblokkeerde threads doorgaan. Er is geen gegarandeerde volgorde, zoals first-in, first-out (FIFO) of last-in, first-out (LIFO), voor geblokkeerde threads om het semafoor te betreden.

Een thread kan meerdere keren de semafoor invoeren door herhaaldelijk de System.Threading.Semaphore-methode van het WaitOne-object of de SemaphoreSlim-methode van het Wait-object aan te roepen. Als u de reemafor wilt vrijgeven, kan de thread hetzelfde aantal keren de Semaphore.Release() of SemaphoreSlim.Release() methode overbelasten, of de overbelasting van de Semaphore.Release(Int32) methode SemaphoreSlim.Release(Int32) aanroepen en het aantal vermeldingen opgeven dat moet worden vrijgegeven.

Semaforen en thread-identiteit

De twee semaphoretypen dwingen geen threadidentiteit af bij het aanroepen van de WaitOne, Wait, Release en SemaphoreSlim.Release methoden. Een gebruikelijk gebruiksscenario voor semaphores omvat bijvoorbeeld een producentthread en een consumententhread, waarbij één thread altijd de semaphorewaarde verhoogt en de andere deze altijd decrementeert.

Het is de verantwoordelijkheid van de programmeur om ervoor te zorgen dat een thread niet te vaak de semafore vrijgeeft. Stel dat een semaphore een maximumaantal van twee heeft en dat thread A en thread B beide de semaphore binnenkomen. Als een programmeerfout in thread B ervoor zorgt dat Release twee keer wordt aangeroepen, slagen beide aanroepen. Het aantal op de semaphore is vol, en wanneer thread A Release aanroept, uiteindelijk wordt er een SemaphoreFullException gegenereerd.

Benoemde semafoor

Met het Windows-besturingssysteem kunnen semaforen namen hebben. Een benoemde semafoor is systeembreed. Zodra de benoemde semaphore is gemaakt, is deze zichtbaar voor alle threads in alle processen. Benoemde semaforen kunnen dus worden gebruikt om de activiteiten van processen en threads te synchroniseren.

U kunt een Semaphore object maken dat een benoemd systeememafore vertegenwoordigt met behulp van een van de constructors die een naam specificeert.

Opmerking

Omdat benoemde semaphores systeembreed zijn, is het mogelijk om meerdere Semaphore objecten te hebben die dezelfde benoemde semaphore vertegenwoordigen. Telkens wanneer u een constructor of methode Semaphore.OpenExisting aanroept, wordt er een nieuw Semaphore object gemaakt. Als u dezelfde naam opgeeft, worden meerdere objecten gemaakt die dezelfde benoemde semaphore vertegenwoordigen.

Wees voorzichtig wanneer u benoemde semaforen gebruikt. Omdat ze systeembreed zijn, kan een ander proces dat dezelfde naam gebruikt uw semaphore onverwacht invoeren. Schadelijke code die op dezelfde computer wordt uitgevoerd, kan dit gebruiken als basis van een denial-of-service-aanval.

Gebruik de beveiliging van toegangsbeheer om een Semaphore object te beveiligen dat een benoemde semafore vertegenwoordigt, bij voorkeur met behulp van een constructor die een System.Security.AccessControl.SemaphoreSecurity object opgeeft. U kunt ook de beveiliging van toegangsbeheer toepassen met behulp van de Semaphore.SetAccessControl methode, maar dit laat een beveiligingsvenster achter tussen de tijd dat de semafor wordt gemaakt en de tijd waarop deze is beveiligd. Het beveiligen van semaphores met beveiliging voor toegangsbeheer helpt schadelijke aanvallen te voorkomen, maar lost het probleem van onbedoelde naamconflicten niet op.

Zie ook