2010-08-19 5 views
60

Sarà solo restituire false se il dizionario non contiene un valore per la chiave dato o intende anche restituire false a causa di infilare condizioni di gara, come un altro thread aggiunge/aggiornamenti qualcosa?Quando si ConcurrentDictionary TryRemove return false

Domanda in codice:

ConcurrentDictionary<int, string> cd = new ConcurrentDictionary<int, string>(); 

// This might fail if another thread is adding with key value of 1. 
cd.TryAdd(1, "one"); 

// Will this ever fail if no other thread ever removes with the key value of 1? 
cd.TryRemove(1); 

Edit: Penso che solo restituirà false se non contiene un valore per la chiave data, ma vuole essere assolutamente sicuro.

risposta

63

Mentre Mitch is right che un ConcurrentDictionary non è vulnerabile a condizioni di gara, credo che la risposta alla domanda che stai chiedendo è che sì, se la chiave è presente, TryRemove funzionerà e tornerà true.

Nel codice che hai postato, non è possibile che TryRemove restituisca false poiché cd è una variabile locale non accessibile da nessun'altra parte. Ma se a qualche altro codice fosse stato dato un riferimento a questo oggettoe stessimo rimuovendo chiavi su un thread separato, allora è possibile che TryRemove restituisca false, anche qui - ma solo perché la chiave era già stata rimossa, non perché qualche altro l'azione viene eseguita sul dizionario e la chiave è in qualche modo "bloccata" lì.

5

Il ConcurrentDictionary non soffre di condizioni di gara. Ecco perché lo usi.

Return Value

vero se un oggetto è stato rimosso con successo ; altrimenti, falso.

1

Un altro punto da fare:

// This might fail if another thread is adding with key value of 1. 
cd.TryAdd(1, "one"); 

Questo commento non è corretto e forse soffre dello stesso equivoco su ciò che significa 'provare'. Non si tratta di un tentativo di concomitante di aggiungere, è se un valore è già stata aggiunta con chiave 1.

consideri uno standard Dictionary<TKey,TValue>. Il codice equivalente sarebbe:

if (!d.Contains(1)) 
    d.Add(1, "one"); 

Ciò richiede due operazioni. Non c'è modo di progettare questa API in modo che risulti protetta da thread, poiché cd potrebbe avere un valore con la chiave 1 aggiunta tra la chiamata a Contains e Add, che comporterebbe quindi il lancio Add.

Le raccolte simultanee hanno API in grado di unire logicamente queste coppie test-and-do in operazioni atomiche singoli, dietro una singola API.