Synkronisera data för multitrådning
När flera trådar kan anropa egenskaperna och metoderna för ett enskilt objekt är det viktigt att dessa anrop synkroniseras. Annars kan en tråd avbryta vad en annan tråd gör och objektet kan lämnas i ett ogiltigt tillstånd. En klass vars medlemmar skyddas mot sådana avbrott kallas trådsäker.
.NET innehåller flera strategier för att synkronisera åtkomst till instanser och statiska medlemmar:
Synkroniserade kodregioner. Du kan använda Monitor-klassen eller kompilatorstöd för den här klassen för att endast synkronisera det kodblock som behöver det, vilket förbättrar prestandan.
Manuell synkronisering. Du kan använda synkroniseringsobjekten som tillhandahålls av .NET-klassbiblioteket. Se Översikt över synkroniseringsprimiterar, som innehåller en diskussion om klassen Monitor.
Synkroniserade kontexter. Endast för .NET Framework-program kan du använda SynchronizationAttribute för att aktivera enkel, automatisk synkronisering för ContextBoundObject objekt.
Samlingsklasser i System.Collections.Concurrent namnrymd. Dessa klasser tillhandahåller inbyggda synkroniserade åtgärder för att lägga till och ta bort. Mer information finns i Thread-Safe samlingar.
Den vanliga språkkörningen tillhandahåller en trådmodell där klasser delas in i ett antal kategorier som kan synkroniseras på olika sätt beroende på kraven. I följande tabell visas vilket synkroniseringsstöd som ges för fält och metoder med en viss synkroniseringskategori.
Kategori | Globala fält | Statiska fält | Statiska metoder | Instansfält | Instansmetoder | Specifika kodblock |
---|---|---|---|---|---|---|
Ingen synkronisering | Nej | Nej | Nej | Nej | Nej | Nej |
Synkroniserad kontext | Nej | Nej | Nej | Ja | Ja | Nej |
Synkroniserade kodregioner | Nej | Nej | Endast om markerat | Nej | Endast om markerat | Endast om markerat |
Manuell synkronisering | Handbok | Handbok | Handbok | Handbok | Handbok | Handbok |
Ingen synkronisering
Detta är standardvärdet för objekt. Alla trådar kan komma åt valfri metod eller fält när som helst. Endast en tråd i taget bör komma åt dessa objekt.
Manuell synkronisering
.NET-klassbiblioteket innehåller ett antal klasser för synkronisering av trådar. Se översikt över synkroniseringsprimitiver.
Synkroniserade kodregioner
Du kan använda klassen Monitor eller ett nyckelord för kompilatorn för att synkronisera block med kod, instansmetoder och statiska metoder. Det finns inget stöd för synkroniserade statiska fält.
Både Visual Basic och C# stöder märkning av kodblock med ett visst språknyckelord, lock
-instruktionen i C# eller SyncLock
-instruktionen i Visual Basic. När koden körs av en tråd görs ett försök att förvärva låset. Om låset redan har hämtats av en annan tråd blockerar tråden tills låset blir tillgängligt. När tråden avslutar det synkroniserade kodblocket släpps låset, oavsett hur tråden avslutar blocket.
Not
Från och med C# 13 identifierar lock
-instruktionen om det låsta objektet är en instans av System.Threading.Lock och använder metoden EnterScope
för att skapa en synkroniserad region.
lock
, när målet inte är en Lock
-instans och SyncLock
-instruktioner implementeras med hjälp av Monitor.Enter och Monitor.Exit, så att andra metoder för Monitor kan användas tillsammans med dem i den synkroniserade regionen.
Du kan också dekorera en metod med en MethodImplAttribute med värdet MethodImplOptions.Synchronized, som har samma effekt som att använda Monitor eller något av nyckelorden i kompilatorn för att låsa hela metodens brödtext.
Thread.Interrupt kan användas för att bryta en tråd från blockeringsåtgärder, till exempel väntar på åtkomst till en synkroniserad kodregion. Thread.Interrupt används också för att bryta trådar ur åtgärder som Thread.Sleep.
Viktig
Lås inte typen – det är typeof(MyType)
i C#, GetType(MyType)
i Visual Basic eller MyType::typeid
i C++ – för att skydda static
-metoder (Shared
-metoder i Visual Basic). Använd ett privat statiskt objekt i stället. På samma sätt ska du inte använda this
i C# (Me
i Visual Basic) för att låsa instansmetoder. Använd ett privat objekt i stället. En klass eller instans kan låsas av annan kod än din egen, vilket kan orsaka dödlägen eller prestandaproblem.
Stöd för kompilator
Både Visual Basic och C# stöder ett språknyckelord som använder Monitor.Enter och Monitor.Exit för att låsa objektet. Visual Basic stöder instruktionen SyncLock; C# stöder instruktionen lock.
I båda fallen, om ett undantag utlöses i kodblocket, frigörs låset som hämtas av låset eller SyncLock- automatiskt. C#- och Visual Basic-kompilatorerna genererar en prova/ blockera med Monitor.Enter i början av försöket och Monitor.Exit i slutligen block. Om ett undantag utlöses i -låset eller SyncLock--blocket så körs finally--hanteraren, vilket gör att du kan utföra rensningsarbete.
Synkroniserad kontext
Endast i .NET Framework-program kan du använda SynchronizationAttribute på alla ContextBoundObject för att synkronisera alla instansmetoder och fält. Alla objekt i samma kontextdomän delar samma lås. Flera trådar kan komma åt metoderna och fälten, men endast en enda tråd tillåts samtidigt.