2010-10-22 8 views
10
lock(dictionaryX) 
{ 
    dictionaryX.TryGetValue(key, out value); 
} 

¿Es necesario el bloqueo mientras se realizan búsquedas en un diccionario?¿Es necesario el bloqueo para la búsqueda del diccionario?

El programa es multiproceso, y al agregar la clave/valor a dict. dict está siendo bloqueado.

+1

si su pregunta es seria y se refiere a programas multiproceso, por favor asegúrese de mencionarlo explícitamente en su pregunta. –

+3

mi pregunta no era tan seria como tu comentario. – DarthVader

Respuesta

2

El bloqueo solo es necesario cuando sincroniza el acceso a un recurso entre subprocesos. Siempre que no haya múltiples hilos implicados, entonces no es necesario el bloqueo aquí.

En el contexto de actualizar y leer el valor de varios hilos, sí, un bloqueo es absolutamente necesario. De hecho, si usa 4.0, debería considerar cambiar a una de las colecciones diseñadas específicamente para el acceso concurrente.

+2

incluso para búsquedas? mientras escribes, ya está bloqueado. – DarthVader

+1

@ user177883 ninguna operación en 'Diccionario' requiere un bloqueo a menos que haya múltiples hilos implicados – JaredPar

+0

También mencioné que el diccionario está siendo bloqueado mientras le agrego datos. pero ¿por qué lo bloquearía de nuevo, mientras hacía la búsqueda? ¿Eso significa que todavía puedo hacer búsquedas mientras dict está bloqueado para escrituras? – DarthVader

0

Sí, debe bloquear si este diccionario es un recurso compartido entre más de un hilo. Esto garantiza que obtenga el valor correcto y que no ocurra otro subproceso que cambie el valor a mitad de camino durante su llamada de búsqueda.

10

Como se ha mencionado here:

Usando TryGetValue() sin bloqueo no es seguro. El diccionario está temporalmente en un estado que lo hace inadecuado para leer mientras otro hilo está escribiendo el diccionario. Un diccionario se reorganizará de vez en cuando a medida que crezca el número de entradas que contiene. Cuando lee en el momento exacto en que se lleva a cabo esta reorganización, correrá el riesgo de encontrar el valor incorrecto para la clave cuando los depósitos se actualizaron pero aún no las entradas de valor.

ACTUALIZACIÓN: echar un vistazo a la parte "Seguridad para subprocesos" de this page también.

+0

Esto solo es cierto cuando se trata de enhebrar. Sin enhebrar, no se necesita bloqueo. – JaredPar

+3

OP mencionó explícitamente que esta operación se lleva a cabo en un entorno multiproceso. –

+1

Estoy de acuerdo. Pero el autor de la pregunta significa usar el bloqueo en un entorno de subprocesos múltiples. – Kamyar

1

Sí, necesita bloquear el diccionario para acceder en un entorno multiproceso. La escritura en un diccionario no es atómica, por lo que podría agregar la clave, pero no el valor. En ese caso, cuando acceda, puede obtener una excepción.

+0

no para escribir, para leer. – DarthVader

+0

@ user177 sí, estaba hablando de leer. Cuando mencioné la escritura, es un ejemplo de lo que podría pasar durante el tiempo que estás tratando de leer. –

3

Al igual que con muchas preguntas sutiles en la programación, la respuesta es: No necesariamente.

Si solo agrega valores como inicialización, no será necesario sincronizar la lectura subsiguiente. Pero, por otro lado, si vas a estar leyendo y escribiendo en todo momento, entonces absolutamente necesitas proteger ese recurso.

Sin embargo, un lock completo puede no ser la mejor manera, dependiendo de la cantidad de tráfico que recibe su diccionario. Pruebe ReaderWriterLockSlim si está usando .NET 3.5 o superior.

+2

+1: Si bien vale la pena intentarlo, es * muy * probable que 'ReaderWriterLockSlim' sea más lento que un simple' viejo 'bloqueo en esta situación ... mucho más lento de hecho.En mis propias pruebas personales, he descubierto que 'ReaderWriterLockSlim' tiene aproximadamente 5 veces la sobrecarga y el antiguo' ReaderWriterLock' es de aproximadamente 15x. Un bloqueo RW tiene un rango de aplicación mucho más estrecho que un 'bloqueo' normal y, como tal, será más lento en la mayoría de las situaciones. Los bloqueos RW realmente brillan cuando el bloqueo se mantiene durante un tiempo prolongado y el número de escritores supera al de los lectores por un amplio margen. Sin embargo, vale la pena compararlo. –

3

Si tiene varios hilos que acceden al Diccionario, entonces necesita bloquear las actualizaciones y la búsqueda. La razón por la que necesita bloquear la búsqueda es que podría haber una actualización al mismo tiempo que hace la búsqueda, y el diccionario podría estar en un estado incoherente durante la actualización. Por ejemplo, imagine que su haber un hilo haciendo esto:

if (myDictionary.TryGetValue(key, out value)) 
{ 
} 

y un hilo separado está haciendo esto:

myDictionary.Remove(key); 

Lo que puede ocurrir es que el hilo haciendo el TryGetValue determina que el artículo esté en el diccionario, pero antes de que pueda recuperar el elemento, el otro hilo lo elimina.El resultado sería que el hilo que realiza la búsqueda arrojaría una excepción o TryGetValue devolvería true pero el value sería null o posiblemente un objeto que no coincida con la clave.

Eso es solo una cosa que puede suceder. Algo similarmente desastroso puede suceder si está realizando una búsqueda en un hilo y otro hilo agrega el valor que está tratando de buscar.

2

Use new ConcurrentDictionary<TKey, TValue> object y puede olvidarse de tener que hacer bloqueos.

+0

No puede olvidarse de todos los bloqueos. Si hace esto en un ConcurrentDictionary: 'if (concDic.Contains (" key "))' 'concDic [" key "]. Do();' Puede obtener una excepción, ya que esta clave puede eliminarse entre el if y el Do(). – Coder14

0

Sí, debe bloquear si tiene actualizaciones multiproceso en ese diccionario. Marque este gran post para más detalles: “Thread safe” Dictionary(TKey,TValue)

Pero desde ConcurrentDictionary<> una presentación que se puede utilizar ya sea a través de .NET 4 o utilizando Rx en 3.5 (que contiene System.Threading.dll con la implementación de nuevas colecciones seguras para subprocesos)

Cuestiones relacionadas