Una raccolta thread-safe rispetto a una raccolta non thread-safe può essere considerata in modo diverso.
Prendi in considerazione un negozio senza commesso, tranne alla cassa. Hai un sacco di problemi se le persone non agiscono in modo responsabile. Ad esempio, supponiamo che un cliente prenda una lattina da una piramide mentre un impiegato sta costruendo la piramide, si scatenerà l'inferno. Oppure cosa succede se due clienti raggiungono contemporaneamente lo stesso oggetto, chi vince? Ci sarà una rissa? Questa è una raccolta non thread-safe. Esistono molti modi per evitare problemi, ma tutti richiedono un qualche tipo di blocco, o piuttosto un accesso esplicito in un modo o nell'altro.
D'altra parte, considera un negozio con un impiegato alla scrivania e puoi solo fare acquisti attraverso di lui. Ti metti in fila e gli chiedi un oggetto, te lo riporta e tu esci dalla fila. Se hai bisogno di più articoli, puoi solo raccogliere tutti gli articoli su ogni roundtrip che ricordi, ma devi fare attenzione a evitare di fare il commesso, questo farà arrabbiare gli altri clienti in fila dietro di te.
Ora considera questo. Nel negozio con un impiegato, cosa succede se arrivi fino in fondo alla fila e chiedi all'impiegato "Hai della carta igienica", e lui dice "Sì", e poi vai "Ok, io ' Ti risponderò quando saprò di cosa ho bisogno ", poi quando sarai di nuovo in prima fila, il negozio potrà ovviamente essere esaurito. Questo scenario non è impedito da una raccolta thread-safe.
Una raccolta thread-safe garantisce che le sue strutture di dati interne siano sempre valide, anche se vi si accede da più thread.
Una collezione non thread-safe non viene fornita con tali garanzie. Ad esempio, se aggiungi qualcosa a un albero binario su un thread, mentre un altro thread è impegnato a riequilibrare l'albero, non vi è alcuna garanzia che l'elemento verrà aggiunto, o anche che l'albero sia ancora valido in seguito, potrebbe essere corrotto oltre ogni speranza.
Una raccolta thread-safe, tuttavia, non garantisce che le operazioni sequenziali sul thread funzionino tutte sullo stesso "snapshot" della sua struttura di dati interna, il che significa che se si dispone di codice come questo:
if (tree.Count > 0)
Debug.WriteLine(tree.First().ToString());
potresti ottenere una NullReferenceException perché tra tree.Count
e tree.First()
, un altro thread ha cancellato i nodi rimanenti nella struttura, il che significa First()
che tornerà null
.
Per questo scenario, è necessario vedere se la raccolta in questione ha un modo sicuro per ottenere ciò che si desidera, forse è necessario riscrivere il codice sopra o potrebbe essere necessario bloccare.