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-semafore-object. Win32-semaforen tellen semaforen, die kunnen worden gebruikt om de toegang tot een groep 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 annuleringstokens, maar biedt geen ondersteuning voor benoemde semaphores of het gebruik van een wachtgreep voor synchronisatie.

Een beperkte resource beheren

Threads voeren deemafore in 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 methode SemaphoreSlim.WaitAsync , in het geval van een SemaphoreSlim object. Wanneer de aanroep wordt geretourneerd, wordt de telling van de semaphore afgebroken. Wanneer een thread invoer aanvraagt en het aantal nul is, worden de threadblokken geblokkeerd. Wanneer threads de semaphore vrijgeven door de Semaphore.Release of SemaphoreSlim.Release methode aan te roepen, mogen geblokkeerde threads worden ingevoerd. Er is geen gegarandeerde volgorde, zoals first-in, first-out (FIFO) of last-in, first-out (LIFO), voor geblokkeerde threads om de semafore in te voeren.

Een thread kan meerdere keren deemafore invoeren door de methode van WaitOne het System.Threading.Semaphore object of de methode van Wait het SemaphoreSlim object herhaaldelijk 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.

Semaphores en Thread Identity

De twee typenemafore dwingen geen threadidentiteit af bij aanroepen naar de WaitOne, Waiten ReleaseSemaphoreSlim.Release methoden. Een gemeenschappelijk gebruiksscenario voor semaphores omvat bijvoorbeeld een producentthread en een consumententhread, waarbij één thread altijd het aantal semaphore en de andere altijd afschadigt.

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

Benoemde semaphores

Met het Windows-besturingssysteem kunnen semaforen namen hebben. Een benoemde semafore is systeembreed. Zodra de benoemde semaphore is gemaakt, is deze zichtbaar voor alle threads in alle processen. Benoemde semafore kan 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.

Notitie

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 semaphores 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