Kritieke sectieobjecten
Een kritiek sectieobject biedt synchronisatie die vergelijkbaar is met die van een mutex-object, behalve dat een kritieke sectie alleen kan worden gebruikt door de threads van één proces. Kritieke sectieobjecten kunnen niet worden gedeeld tussen processen.
Gebeurtenis-, mutex- en semaphore-objecten kunnen ook worden gebruikt in een toepassing met één proces, maar kritieke sectieobjecten bieden een iets sneller, efficiënter mechanisme voor wederzijdse uitsluitingssynchronisatie (een processorspecifieke test en set-instructie). Net als een mutex-object kan een kritiek sectieobject eigendom zijn van slechts één thread tegelijk, waardoor het handig is voor het beveiligen van een gedeelde resource tegen gelijktijdige toegang. In tegenstelling tot een mutex-object is er geen manier om te zien of een kritieke sectie is verlaten.
Vanaf Windows Server 2003 met Service Pack 1 (SP1) verkrijgen threads die wachten op een kritieke sectie niet de kritieke sectie op basis van de eerste kom, eerste server. Deze wijziging verhoogt de prestaties aanzienlijk voor de meeste code. Sommige toepassingen zijn echter afhankelijk van fifo-volgorde (first-in, first-out) en presteren mogelijk slecht of helemaal niet op de huidige versies van Windows (bijvoorbeeld toepassingen die kritieke secties als frequentielimiet gebruiken). Om ervoor te zorgen dat uw code correct blijft werken, moet u mogelijk een extra synchronisatieniveau toevoegen. Stel dat u een producerthread en een consumententhread hebt die een kritiek sectieobject gebruiken om hun werk te synchroniseren. Maak twee gebeurtenisobjecten, één voor elke thread die moet worden gebruikt om aan te geven dat deze gereed is voor de andere thread om door te gaan. De consumententhread wacht totdat de producent de gebeurtenis aangeeft voordat deze de kritieke sectie invoert. De producerthread wacht totdat de consumententhread de gebeurtenis aangeeft voordat de kritieke sectie wordt ingevoerd. Nadat elke thread de kritieke sectie verlaat, wordt de gebeurtenis signalen afgegeven om de andere thread vrij te geven.
Windows Server 2003 en Windows XP: threads die op een kritieke sectie wachten, worden toegevoegd aan een wachtwachtrij; ze worden wakker en verwerven over het algemeen de kritieke sectie in de volgorde waarin ze aan de wachtrij zijn toegevoegd. Als threads echter snel genoeg aan deze wachtrij worden toegevoegd, kunnen de prestaties worden verminderd vanwege de tijd die nodig is om elke wachtende thread te laten ontwaken.
Het proces is verantwoordelijk voor het toewijzen van het geheugen dat wordt gebruikt door een kritieke sectie. Dit wordt meestal gedaan door simpelweg een variabele van het type CRITICAL_SECTIONte declareren. Voordat de threads van het proces dit kunnen gebruiken, initialiseert u de kritieke sectie met behulp van de functie InitializeCriticalSection of InitializeCriticalSectionAndSpinCount.
Een thread maakt gebruik van de functie EnterCriticalSection of TryEnterCriticalSection functie om het eigendom van een kritieke sectie aan te vragen. Hierbij wordt de functie LeaveCriticalSection gebruikt om het eigendom van een kritieke sectie vrij te geven. Als het kritieke sectieobject momenteel eigendom is van een andere thread, EnterCriticalSection wacht voor onbepaalde tijd op eigendom. Wanneer een mutex-object daarentegen wordt gebruikt voor wederzijdse uitsluiting, accepteren de wachtfuncties een opgegeven time-outinterval accepteren. De TryEnterCriticalSection functie probeert een kritieke sectie in te voeren zonder de aanroepende thread te blokkeren.
Wanneer een thread eigenaar is van een kritieke sectie, kan deze extra aanroepen uitvoeren naar EnterCriticalSection of TryEnterCriticalSection zonder de uitvoering ervan te blokkeren. Hiermee voorkomt u dat een thread zichzelf blokkeert terwijl wordt gewacht op een kritieke sectie die al eigenaar is. Als u het eigendom ervan wilt vrijgeven, moet de thread LeaveCriticalSection één keer aanroepen telkens wanneer deze de kritieke sectie heeft ingevoerd. Er is geen garantie over de volgorde waarin wachtende threads eigenaar worden van de kritieke sectie.
Een thread maakt gebruik van de functie InitializeCriticalSectionAndSpinCount of SetCriticalSectionSpinCount om een spintelling voor het kritieke sectieobject op te geven. Draaien betekent dat wanneer een thread probeert een kritieke sectie te verkrijgen die is vergrendeld, de thread een lus binnenkomt, controleert of de vergrendeling wordt vrijgegeven en als de vergrendeling niet wordt losgelaten, de thread in de slaapstand gaat. Op systemen met één processor wordt het aantal spinnen genegeerd en wordt het aantal kritieke secties ingesteld op 0 (nul). Als de kritieke sectie niet beschikbaar is op multiprocessorsystemen, draait de aanroepende thread dwSpinCount keer voordat een wachtbewerking wordt uitgevoerd op een semafore die is gekoppeld aan de kritieke sectie. Als de kritieke sectie vrij wordt tijdens de spinbewerking, voorkomt de aanroepende thread de wachtbewerking.
Elke thread van het proces kan de DeleteCriticalSection functie gebruiken om de systeemresources vrij te geven die worden toegewezen wanneer het kritieke sectieobject wordt geïnitialiseerd. Nadat deze functie is aangeroepen, kan het kritieke sectieobject niet worden gebruikt voor synchronisatie.
Wanneer een kritiek sectieobject eigendom is, zijn de enige andere betrokken threads de threads die wachten op eigendom in een aanroep naar EnterCriticalSection. Threads die niet wachten, kunnen worden uitgevoerd.
Verwante onderwerpen