Condividi tramite


Sincronizzazione dei dati per il multithreading

Aggiornamento: novembre 2007

Quando più thread consentono di effettuare chiamate alle proprietà e ai metodi di un singolo oggetto, è indispensabile che tali chiamate siano sincronizzate. In caso contrario, un thread potrebbe interrompere le operazioni di un altro thread e lo stato dell'oggetto potrebbe risultare non valido. Una classe i cui membri sono protetti da tali interruzioni è detta thread-safe.

Common Language Infrastructure offre diverse strategie per sincronizzare l'accesso a membri di istanza e statici:

Common Language Runtime fornisce un modello di thread in cui le classi rientrano in diverse categorie che è possibile sincronizzare in vari modi a seconda dei requisiti. Nella tabella che segue viene indicato il tipo di supporto alla sincronizzazione fornito per campi e metodi con una determinata categoria di sincronizzazione.

Categoria

Campi globali

Campi statici

Metodi statici

Campi di istanza

Metodi di istanza

Blocchi di codice specifici

Nessuna sincronizzazione

No

No

No

No

No

No

Contesto di sincronizzazione

No

No

No

No

Aree del codice sincronizzate

No

No

Solo se contrassegnato

No

Solo se contrassegnato

Solo se contrassegnato

Sincronizzazione manuale

Manuale

Manuale

Manuale

Manuale

Manuale

Manuale

Nessuna sincronizzazione

Si tratta dell'impostazione predefinita per gli oggetti. Ogni thread può accedere a qualsiasi metodo o campo in qualsiasi momento. Solo un thread alla volta deve poter accedere a questi oggetti.

Sincronizzazione manuale

La libreria delle classi .NET Framework fornisce una serie di classi per la sincronizzazione dei thread. Per informazioni al riguardo, vedere Cenni preliminari sulle primitive di sincronizzazione.

Aree del codice sincronizzate

È possibile utilizzare la classe Monitor o una parola chiave del compilatore per sincronizzare blocchi di codice, metodi di istanza e metodi statici. Non è disponibile alcun supporto per i campi statici sincronizzati.

Sia con Visual Basic che con C# è possibile contrassegnare blocchi di codice con una particolare parola chiave del linguaggio, l'istruzione lock in C# o SyncLock in Visual Basic. Quando il codice viene eseguito da un thread, viene effettuato un tentativo di acquisire il blocco. Se il blocco è già stato acquisito da un altro thread, il thread corrente si blocca finché il blocco non diventa disponibile. Quando il thread esce dal blocco di codice sincronizzato, il blocco viene rilasciato, indipendentemente dalla modalità di uscita del thread dal blocco di codice.

Nota:

Le istruzioni lock e SyncLock vengono implementate tramite Monitor.Enter e Monitor.Exit, pertanto è possibile utilizzare insieme altri metodi di Monitor all'interno dell'area sincronizzata.

È anche possibile decorare un metodo con MethodImplAttribute e MethodImplOptions.Synchronized, in modo da avere lo stesso effetto di quando si utilizza Monitor o una delle parole chiave del compilatore per bloccare l'intero corpo del metodo.

Thread.Interrupt può essere utilizzato per interrompere le operazioni di blocco di un thread, quali l'attesa di accesso a un'area sincronizzata di codice. Thread.Interrupt viene utilizzato anche per interrompere operazioni del thread quali Thread.Sleep.

Nota importante:

Non bloccare il tipo, ovvero typeof(MyType) in C#, GetType(MyType) in Visual Basic o MyType::typeid in C++, per proteggere i metodi static (i metodi Shared in Visual Basic). Utilizzare invece un oggetto statico privato. Analogamente, non utilizzare this in C# (Me in Visual Basic) per bloccare i metodi di istanza. Utilizzare invece un oggetto privato. Una classe o istanza può venire bloccata da codice diverso da quello che si sta sviluppando, con conseguenti possibili deadlock o problemi di prestazioni.

Supporto del compilatore

Sia Visual Basic che C# supportano una parola chiave del linguaggio che utilizza Monitor.Enter e Monitor.Exit per bloccare l'oggetto. Visual Basic supporta l'istruzione SyncLock, mentre C# supporta l'istruzione lock.

In entrambi i casi, se viene generata un'eccezione nel blocco di codice, il blocco acquisito da lock o da SyncLock viene rilasciato automaticamente. I compilatori C# e Visual Basic creano un costrutto try/finally con Monitor.Enter all'inizio e Monitor.Exit nel costrutto finally. Se un'eccezione viene generata all'interno del blocco lock o SyncLock, il gestore finally viene eseguito per consentire l'esecuzione di eventuale lavoro di pulizia.

Contesto di sincronizzazione

È possibile utilizzare SynchronizationAttribute su qualsiasi ContextBoundObject per sincronizzare tutti i metodi e i campi di istanza. Tutti gli oggetti nello stesso dominio del contesto condividono lo stesso blocco. I thread multipli possono accedere a metodi e campi, ma è consentito solo ad un singolo thread alla volta.

Vedere anche

Concetti

Thread e threading

Cenni preliminari sulle primitive di sincronizzazione

Riferimenti

Istruzione SyncLock

Istruzione lock (Riferimenti per C#)

SynchronizationAttribute