Kritiska avsnittsobjekt
Ett kritiskt avsnittsobjekt tillhandahåller synkronisering som liknar den som tillhandahålls av ett mutex-objekt, förutom att ett kritiskt avsnitt endast kan användas av trådarna i en enda process. Kritiska avsnittsobjekt kan inte delas mellan processer.
Händelse-, mutex- och semaforobjekt kan också användas i ett program med en enda process, men kritiska avsnittsobjekt ger en något snabbare och effektivare mekanism för synkronisering av ömsesidig uteslutning (ett processorspecifikt test och uppsättningsinstruktioner). Precis som ett mutex-objekt kan ett kritiskt avsnittsobjekt bara ägas av en tråd i taget, vilket gör det användbart för att skydda en delad resurs från samtidig åtkomst. Till skillnad från ett mutex-objekt finns det inget sätt att avgöra om ett kritiskt avsnitt har avbrutits.
Från och med Windows Server 2003 med Service Pack 1 (SP1) hämtar trådar som väntar på ett kritiskt avsnitt inte det kritiska avsnittet först till kvarn. Den här ändringen ökar prestanda avsevärt för de flesta kod. Vissa program är dock beroende av först-i-först-ut-ordning (FIFO) och kan fungera dåligt eller inte alls på aktuella versioner av Windows (till exempel program som har använt kritiska avsnitt som hastighetsbegränsning). För att säkerställa att koden fortsätter att fungera korrekt kan du behöva lägga till ytterligare en synkroniseringsnivå. Anta till exempel att du har en producenttråd och en konsumenttråd som använder ett kritiskt avsnittsobjekt för att synkronisera sitt arbete. Skapa två händelseobjekt, ett för varje tråd som ska användas för att signalera att den är redo för den andra tråden att fortsätta. Konsumenttråden väntar på att producenten ska signalera händelsen innan den går in i det kritiska avsnittet, och producenttråden väntar på att konsumenttråden ska signalera händelsen innan den går in i det kritiska avsnittet. När varje tråd lämnar det kritiska avsnittet signalerar den sin händelse för att släppa den andra tråden.
Windows Server 2003 och Windows XP: trådar som väntar på ett kritiskt avsnitt läggs till i en väntekö. de väcks och skaffar vanligtvis det kritiska avsnittet i den ordning de lades till i kön. Men om trådar läggs till i den här kön med en tillräckligt snabb hastighet kan prestandan försämras på grund av den tid det tar att väcka varje väntande tråd.
Processen ansvarar för att allokera det minne som används av ett kritiskt avsnitt. Detta görs vanligtvis genom att helt enkelt deklarera en variabel av typen CRITICAL_SECTION. Innan trådarna i processen kan använda den initierar du det kritiska avsnittet med hjälp av funktionen InitializeCriticalSection eller InitializeCriticalSectionAndSpinCount.
En tråd använder funktionen EnterCriticalSection eller TryEnterCriticalSection för att begära ägarskap för ett kritiskt avsnitt. Den använder funktionen LeaveCriticalSection för att frigöra ägarskapet för ett kritiskt avsnitt. Om det kritiska avsnittsobjektet för närvarande ägs av en annan tråd väntar EnterCriticalSection på obestämd tid på ägarskap. När ett mutex-objekt däremot används för ömsesidigt undantag väntefunktionerna acceptera ett angivet tidsgränsintervall. Funktionen TryEnterCriticalSection försöker ange ett kritiskt avsnitt utan att blockera den anropande tråden.
När en tråd äger ett kritiskt avsnitt kan den göra ytterligare anrop till EnterCriticalSection eller TryEnterCriticalSection utan att blockera körningen. Detta förhindrar att en tråd hindrar sig själv från att låsa sig i väntan på ett kritiskt avsnitt som den redan äger. För att frigöra ägarskapet måste tråden anropa LeaveCriticalSection en gång för varje gång den gick in i det kritiska avsnittet. Det finns ingen garanti för i vilken ordning väntande trådar får ägarskap för det kritiska avsnittet.
En tråd använder funktionen InitializeCriticalSectionAndSpinCount eller SetCriticalSectionSpinCount för att ange ett spinnantal för det kritiska avsnittsobjektet. Spinning innebär att när en tråd försöker hämta ett kritiskt avsnitt som är låst, kommer tråden in i en slinga, kontrollerar om låset släpps och om låset inte släpps, försätts tråden i viloläge. I system med en processor ignoreras antalet spinn och det kritiska antalet sektionsspinn är inställt på 0 (noll). Om det kritiska avsnittet inte är tillgängligt i system med flera processorer snurrar den anropande tråden dwSpinCount gånger innan du utför en vänteåtgärd på en semafor som är associerad med det kritiska avsnittet. Om det kritiska avsnittet blir kostnadsfritt under spinnåtgärden undviker den anropande tråden vänteåtgärden.
Alla trådar i processen kan använda funktionen DeleteCriticalSection för att frigöra systemresurserna som allokeras när det kritiska avsnittsobjektet initieras. När den här funktionen har anropats kan det kritiska avsnittsobjektet inte användas för synkronisering.
När ett kritiskt avsnittsobjekt ägs är de enda andra trådar som påverkas de trådar som väntar på ägarskap i ett anrop till EnterCriticalSection. Trådar som inte väntar kan fortsätta att köras.
Relaterade ämnen