Delen via


Gegevens synchroniseren voor multithreading

Wanneer meerdere threads de eigenschappen en methoden van één object kunnen aanroepen, is het essentieel dat deze aanroepen worden gesynchroniseerd. Anders kan één thread onderbreken wat een andere thread doet en kan het object een ongeldige status hebben. Een klasse waarvan de leden worden beschermd tegen dergelijke onderbrekingen, wordt thread-safe genoemd.

.NET biedt verschillende strategieën voor het synchroniseren van toegang tot exemplaren en statische leden:

  • Gesynchroniseerde coderegio's. U kunt de Monitor klasse- of compilerondersteuning voor deze klasse gebruiken om alleen het codeblok te synchroniseren dat dit nodig heeft, waardoor de prestaties worden verbeterd.

  • Handmatige synchronisatie. U kunt de synchronisatieobjecten van de .NET-klassebibliotheek gebruiken. Zie Overzicht van Synchronization Primitives, waaronder een bespreking van de Monitor klasse.

  • Gesynchroniseerde contexten. Alleen voor .NET Framework- en Xamarin-toepassingen kunt u de SynchronizationAttribute functie gebruiken om eenvoudige, automatische synchronisatie voor ContextBoundObject objecten in te schakelen.

  • Verzamelingsklassen in de System.Collections.Concurrent naamruimte. Deze klassen bieden ingebouwde gesynchroniseerde bewerkingen voor toevoegen en verwijderen. Zie Thread-Safe Collections voor meer informatie.

De algemene taalruntime biedt een threadmodel waarin klassen in een aantal categorieën kunnen worden gesynchroniseerd op verschillende manieren, afhankelijk van de vereisten. In de volgende tabel ziet u welke synchronisatieondersteuning wordt geboden voor velden en methoden met een bepaalde synchronisatiecategorie.

Categorie Globale velden Statische velden Statische methoden Exemplaarvelden Exemplaarmethoden Specifieke codeblokken
Geen synchronisatie Nee No No No No Nr.
Gesynchroniseerde context Nee No No Ja Ja Nr.
Gesynchroniseerde coderegio's Nee Nr. Alleen als deze optie is gemarkeerd Nee Alleen als deze optie is gemarkeerd Alleen als deze optie is gemarkeerd
Handmatige synchronisatie Handmatig Handmatig Handmatig Handmatig Handmatig Handmatig

Geen synchronisatie

Dit is de standaardwaarde voor objecten. Elke thread heeft op elk gewenst moment toegang tot elke methode of elk veld. Slechts één thread tegelijk moet toegang krijgen tot deze objecten.

Handmatige synchronisatie

De .NET-klassebibliotheek biedt een aantal klassen voor het synchroniseren van threads. Zie Overzicht van Synchronisatieprimitief.

Gesynchroniseerde coderegio's

U kunt de Monitor klasse of een compiler-trefwoord gebruiken om codeblokken, exemplaarmethoden en statische methoden te synchroniseren. Er is geen ondersteuning voor gesynchroniseerde statische velden.

Visual Basic en C# ondersteunen het markeren van codeblokken met een bepaald taalwoord, de lock instructie in C# of de SyncLock instructie in Visual Basic. Wanneer de code wordt uitgevoerd door een thread, wordt geprobeerd de vergrendeling te verkrijgen. Als de vergrendeling al is verkregen door een andere thread, wordt de thread geblokkeerd totdat de vergrendeling beschikbaar is. Wanneer de thread het gesynchroniseerde codeblok verlaat, wordt de vergrendeling vrijgegeven, ongeacht hoe de thread het blok verlaat.

Notitie

Vanaf C# 13 herkent de lock instructie of het vergrendelde object een exemplaar is van System.Threading.Lock en gebruikt de EnterScope methode om een gesynchroniseerde regio te maken. De lock, wanneer het doel geen Lock exemplaar is en SyncLock instructies worden geïmplementeerd met behulp Monitor.Enter van en Monitor.Exit, zodat andere methoden Monitor kunnen worden gebruikt in combinatie met deze methoden in de gesynchroniseerde regio.

U kunt ook een methode versieren met een MethodImplAttribute waarde van MethodImplOptions.Synchronized, die hetzelfde effect heeft als het gebruik Monitor van of een van de compilertrefwoorden om de hele hoofdtekst van de methode te vergrendelen.

Thread.Interrupt kan worden gebruikt om een thread uit blokkerende bewerkingen te breken, zoals wachten op toegang tot een gesynchroniseerde coderegio. Thread.Interrupt wordt ook gebruikt om threads uit bewerkingen te breken, zoals Thread.Sleep.

Belangrijk

Vergrendel het type ( in typeof(MyType) C#, GetType(MyType) in Visual Basic of MyType::typeid in C++ ) niet om methoden (Sharedmethoden in Visual Basic) te beveiligenstatic. Gebruik in plaats daarvan een privé statisch object. Gebruik ook niet this in C# (Me in Visual Basic) om exemplaarmethoden te vergrendelen. Gebruik in plaats daarvan een privéobject. Een klasse of exemplaar kan worden vergrendeld door andere code dan uw eigen code, waardoor mogelijk impasses of prestatieproblemen optreden.

Compilerondersteuning

Visual Basic en C# ondersteunen een taalwoord dat het object gebruikt Monitor.Enter en Monitor.Exit vergrendelt. Visual Basic ondersteunt de SyncLock-instructie; C# ondersteunt de vergrendelingsinstructie.

Als er in beide gevallen een uitzondering wordt gegenereerd in het codeblok, wordt de vergrendeling die is verkregen door de vergrendeling of SyncLock automatisch vrijgegeven. De C#- en Visual Basic-compilers verzenden eindelijk een poging/met Monitor.Enter aan het begin van de poging en Monitor.Exit in het laatste blok. Als er een uitzondering binnen het vergrendelings- of SyncLock-blok wordt gegenereerd, wordt de handler uitgevoerd om u te laten opschonen.

Gesynchroniseerde context

In .NET Framework- en Xamarin-toepassingen kunt u alleen de on-any SynchronizationAttributeContextBoundObject gebruiken om alle exemplaarmethoden en -velden te synchroniseren. Alle objecten in hetzelfde contextdomein delen dezelfde vergrendeling. Meerdere threads hebben toegang tot de methoden en velden, maar er is maar één thread tegelijk toegestaan.

Zie ook