DarioSantarelli.Blog("UgiDotNet");

<sharing mode=”On” users=”*” />
posts - 176, comments - 144, trackbacks - 3

My Links

News


This is my personal blog. These postings are provided "AS IS" with no warranties, and confer no rights.




Tag Cloud

Archives

Post Categories

My English Blog

domenica 3 luglio 2011

System.Collections.Concurrent: via tutti i lock!

Per garantire la thread-safety nell’accesso a collezioni di oggetti in contesti multi-thread, fino ad oggi siamo stati abituati ad utilizzare i più svariati meccanismi di lock, magari prevedendo diversi livelli di granularità.
In questo ambito il framework 4.0 fornisce il namespace System.Collections.Concurrent che offre un set di classi thread-safe che si possono usare al posto di quelle di System.Collections e System.Collections.Generic.

Anzitutto, salutiamo con una certa soddisfazione la classe ConcurrentDictionary<TKey, TValue>, versione thread-safe della classe Dictionary.

Vengono forniti poi tre oggetti che implementano IProducerConsumerCollection<T>, un’interfaccia che definisce due metodi TryAdd e TryTake per scenari “producer/consumer”, ovvero scenari in cui più thread aggiungono o rimuovono elementi dalla stessa collection in modo concorrente. Gli oggetti in questione sono:

  • ConcurrentBag<T>: implementazione thread-safe di una collezione non ordinata di elementi (eventualmente duplicabili). Questo oggetto è particolarmente ottimizzato per scenari in cui lo stesso thread produce e consuma gli elementi del bag.
  • ConcurrentQueue<T>: versione concorrente di una coda FIFO. A differenza di quanto si sente dire spesso erroneamente, questa classe non costituisce un semplice wrapper della classe Queue ( tipo Queue.Synchronized() ), bensì qualcosa di più potente e performante che internamente fa uso di meccanismi di sincronizzazione e validazione più ottimizzati basati sulle classi SpinWait e Interlocked.
  • ConcurrentStack<T>: versione concorrente di uno stack LIFO. 

Infine abbiamo l’oggetto BlockingCollection<T>, che di fatto costituisce una classe di più alto livello. Una BlockingCollection è a tutti gli effetti un wrapper di un oggetto che implementa l’interfaccia IProducerConsumerCollection<T> (come i sopra citati ConcurrentBag<T>, ConcurrentQueue<T> e ConcurrentStack<T>). Ciò significa che di suo non implementa un meccanismo di storage interno, bensì introduce soltanto la logica di gestione thread-safe per scenari producer/consumer. Infatti, se non forniamo al costruttore un IProducerConsumerCollection, per default viene istanziata internamente una ConcurrentQueue (FIFO). Poiché la BlockingCollection è utile come buffer di scambio condiviso tra più thread, essa fornisce gratis anche dei meccanismi di blocco (metodi Add() e Take()) grazie ai quali possiamo fare in modo che i thread “producer” si blocchino se la collezione è piena (aspettando quindi che almeno un elemento venga rimosso dalla collezione) oppure viceversa che i thread “consumer” si blocchino quando cercano di rimuovere un elemento dalla collection interna vuota.

posted @ domenica 3 luglio 2011 14.31 | Feedback (0) | Filed Under [ .NET ]

Powered by: