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 klassens eller kompilatorns stö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 synkroniserings primitiver, som innehåller en diskussion om Monitor klassen.
Synkroniserade kontexter. Endast för .NET Framework- och Xamarin-program kan du använda SynchronizationAttribute för att aktivera enkel, automatisk synkronisering för ContextBoundObject objekt.
Samlingsklasser i System.Collections.Concurrent namnområdet. Dessa klasser tillhandahåller inbyggda synkroniserade åtgärder för att lägga till och ta bort. Mer information finns i Thread-Valv Collections (Tråd-Valv-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 | Manuell | Manuell | Manuell | Manuell | Manuell | Manuell |
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 synkroniseringspri primitiver.
Synkroniserade kodregioner
Du kan använda nyckelordet Monitor klass eller kompilator för att synkronisera kodblock, 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, -instruktionen lock
i C# eller -instruktionen SyncLock
i Visual Basic. När koden körs av en tråd görs ett försök att hämta 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.
Kommentar
Från och med C# 13 identifierar instruktionen lock
om det låsta objektet är en instans av System.Threading.Lock och använder EnterScope
metoden för att skapa en synkroniserad region. , lock
när målet inte är en Lock
instans, och SyncLock
-instruktioner implementeras med och Monitor.EnterMonitor.Exit, så att andra metoder Monitor för kan användas tillsammans med dem i den synkroniserade regionen.
Du kan också dekorera en metod med värdet MethodImplAttributeMethodImplOptions.Synchronized, som har samma effekt som att använda Monitor eller något av kompilatornyckelorden för att låsa hela metodens brödtext.
Thread.Interrupt kan användas för att bryta ut en tråd från blockeringsåtgärder som att vänta på åtkomst till en synkroniserad kodregion. Thread.Interrupt används också för att bryta trådar ur åtgärder som Thread.Sleep.
Viktigt!
Lås inte typen , dvs 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 SyncLock-instruktionen. C# stöder lås-instruktionen.
I båda fallen, om ett undantag utlöses i kodblocket, frigörs låset som hämtas av låset eller SyncLock automatiskt. Kompilatorerna C# och Visual Basic genererar ett försök/att slutligen blockera med Monitor.Enter i början av försöket och Monitor.Exit i det sista blocket. Om ett undantag utlöses i låset eller SyncLock-blocket körs slutligen hanteraren så att du kan utföra rensningsarbete.
Synkroniserad kontext
Endast i .NET Framework- och Xamarin-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.