Middle+
Cum se gestionează lucrul cu firele (threads) și sarcinile (tasks) atunci când mai multe dintre ele accesează o stare comună?
sobes.tech AI
Răspuns de la AI
Pentru a accesa în mod sigur starea partajată într-un mediu multi-thread, se utilizează mecanisme de sincronizare.
Abordări principale:
- Blocări:
lockeste cel mai răspândit mecanism. Asigură accesul exclusiv la un bloc de cod sau obiect pentru un singur fir de execuție o dată. Mutex (excludere reciprocă) este, de asemenea, utilizat, dar adesea în interacțiunea între procese. - Semantici: Limitează numărul de fire de execuție care pot accesa simultan o resursă.
- Monitor: Reprezintă o versiune mai puternică a
lock, permițând firelor de execuție să aștepte notificări de la altele. - ReadWriteLock: Permite mai multor fire de execuție să citească datele în același timp, dar doar unuia să scrie.
- Operații atomice: Pentru operații simple (incrementare, decrementare, comparație-schimbare), se pot folosi metode statice ale clasei
Interlocked.
Atunci când lucrați cu sarcini (Tasks), în special cu async/await, este important să vă amintiți că sarcinile nu sunt legate de un fir de execuție specific. Contextele de sincronizare (SynchronizationContext) ajută la revenirea în contextul necesar (de exemplu, firul UI) după finalizarea unei operațiuni asincrone.
Exemplu de utilizare a lock:
// Obiect pentru blocare
private readonly object _lockObject = new object();
private int _sharedCounter = 0;
public void IncrementCounter()
{
// Blocarea accesului la contorul partajat
lock (_lockObject)
{
_sharedCounter++;
}
}
Exemplu de utilizare a Interlocked:
private int _sharedAtomicCounter = 0;
public void IncrementAtomicCounter()
{
// Incrementare atomică
Interlocked.Increment(ref _sharedAtomicCounter);
}