Middle+
Come si gestisce il lavoro con thread e task quando più di essi accedono a uno stato comune?
sobes.tech AI
Risposta dell'AI
Per accedere in modo sicuro allo stato condiviso in un ambiente multithread, vengono utilizzati meccanismi di sincronizzazione.
Approcci principali:
- Blocchi:
lockè il meccanismo più comune. Garantisce l'accesso esclusivo a un blocco di codice o a un oggetto per un solo thread alla volta. Mutex (esclusione mutua) viene anch'esso usato, ma spesso nelle interazioni tra processi. - Semantiche: Limitano il numero di thread che possono accedere contemporaneamente a una risorsa.
- Monitor: Rappresenta una versione più potente di
lock, che permette ai thread di attendere notifiche da altri thread. - ReadWriteLock: Permette a più thread di leggere i dati contemporaneamente, ma solo a uno di scrivere.
- Operazioni atomiche: Per operazioni semplici (incremento, decremento, confronto-sostituzione), si possono usare metodi statici della classe
Interlocked.
Quando si lavora con task (Task), specialmente usando async/await, è importante ricordare che i task non sono legati a un thread specifico. I contesti di sincronizzazione (SynchronizationContext) aiutano a tornare al contesto desiderato (ad esempio, il thread UI) dopo aver completato un'operazione asincrona.
Esempio di utilizzo di lock:
// Oggetto per il blocco
private readonly object _lockObject = new object();
private int _sharedCounter = 0;
public void IncrementCounter()
{
// Blocca l'accesso al contatore condiviso
lock (_lockObject)
{
_sharedCounter++;
}
}
Esempio di utilizzo di Interlocked:
private int _sharedAtomicCounter = 0;
public void IncrementAtomicCounter()
{
// Incremento atomico
Interlocked.Increment(ref _sharedAtomicCounter);
}