2010-08-19 9 views
60

¿Devolverá falso solamente si el diccionario no contiene un valor para la clave dada o también devolverá falso debido a las condiciones de carrera de subproceso, como otro subproceso agrega/actualiza algo?Cuándo ConcurrentDictionary TryRemove devolverá falso

Pregunta en código:

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); 

Editar: Creo que sólo devolverá falso si no contiene un valor para la clave dada, pero quiere estar absolutamente seguro.

Respuesta

63

Mientras que un Mitch is rightConcurrentDictionary no es vulnerable a condiciones de carrera, creo que la respuesta a la pregunta que usted está pidiendo es que sí, si la clave está presente, TryRemove funcionará y volver true.

En el código que ha publicado, no hay forma de que TryRemove devuelva ya que cd es una variable local a la que no se ha accedido en ningún otro lado. Pero si a algún código en otra parte se le hubiera dado una referencia a este objeto ConcurrentDictionary y estuviera eliminando claves en un hilo separado, entonces es posible que TryRemove devuelva , incluso aquí, pero solo porque la clave ya se eliminó, no porque haya alguna otra la acción se está realizando en el diccionario y la clave está de alguna manera "atascada" allí.

5

El ConcurrentDictionary no sufre de condiciones de carrera. Es por eso que lo usas.

Valor de retorno

cierto si un objeto se retira éxito; de lo contrario, falso.

1

Otro punto de hacer:

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

Este comentario es incorrecta y posiblemente sufre de la misma idea errónea acerca de lo que significa 'tratar'. No se trata de un intento simultáneo de agregar, es si ya se ha agregado un valor con la clave 1.

Considere un estándar Dictionary<TKey,TValue>. El código equivalente sería:

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

Esto requiere dos operaciones. No hay forma de diseñar dicha API para que sea segura, ya que cd puede tener un valor con la clave 1 agregada entre la llamada a Contains y Add, lo que resultaría en el lanzamiento de Add.

Las colecciones concurrentes tienen API que agrupan lógicamente estos pares de prueba y acción en operaciones atómicas individuales, detrás de una sola API.

Cuestiones relacionadas