2011-12-22 16 views
9

La documentación para ReadOnlyCollection (de T) establece que:ReadOnlyCollection <T> Seguridad para subprocesos

A ReadOnlyCollection(Of T) puede soportar múltiples lectores al mismo tiempo, siempre y cuando no se modifique la colección. Aun así, enumerar a través de una colección no es intrínsecamente un procedimiento de subprocesos. Para garantizar la seguridad del subproceso durante la enumeración, puede bloquear la recopilación durante toda la enumeración. Para permitir que la colección sea accedida por múltiples hilos para lectura y escritura, debe implementar su propia sincronización.

Mi pregunta se refiere a la parte en negrita:

  1. qué es enumerar a través de una colección intrínsecamente no apta para subprocesos
  2. ¿cuáles son las posibles implicaciones y
  3. ¿qué soluciones-comúnmente usado?
+1

Oh muchacho. He estado luchando contra thread- listas seguras en .NET por mucho tiempo. Vea algunas discusiones previas aquí: http://stackoverflow.com/questions/550616/lock -free-stack-and-queue-in-c-sharp y/o aquí: http://stackoverflow.com/questions/66622/threadsafe-foreach-enumeration-of-lists – Radu094

Respuesta

7

C# tiene un modelo de colección bastante bueno, pero la clase ReadOnlyCollection es una de las clases más desafortunadamente concebidas (o nombradas) en todo el modelo. Debería haberse llamado más apropiadamente una lista de solo lectura, no una colección de solo lectura.

Ahora, para llegar a su pregunta, es solo un decorador de solo lectura de un IList suministrado en tiempo de construcción. Por lo tanto, el código que construyó ReadOnlyCollection puede modificar la lista original, con todas las consecuencias que esto tendrá para el acceso multiproceso.

Por lo tanto, enumerar a través de la colección habría sido seguro para subprocesos si la colección fuera realmente de solo lectura; pero como no es de solo lectura, no es seguro para subprocesos. Dada la cantidad de reputación que tiene, estoy bastante seguro de que no se está preguntando por qué enumerar a través de una colección que no sea de solo lectura no es seguro para subprocesos.

En cuanto a la solución que usted solicitó, bien, puede usar el bloqueo, o puede ir con el principio de bloqueo-nada (o bloquear-como-poco-como-posible) y hacer una verdadera copia de solo lectura de la lista.

EDITAR

estoy releyendo mi respuesta muchos meses después, (gracias a la asyncwait comentario,) y me doy cuenta de que debería haber contestado todas las preguntas de la OP sin hacer suposiciones sobre la base de su reputación. El OP probablemente ya haya recibido su respuesta, pero lo haré por el bien de los futuros lectores.

Enumerar a través de una colección que no es de solo lectura intrínsecamente no es seguro para subprocesos por las mismas razones que incluso en un escenario de subproceso único no se puede modificar una colección al enumerarla. (ConcurrentModificationException en Java, InvalidOperationException en C#.) En un escenario de subproceso único, puede asegurarse de que su código de enumeración no intente alterar la colección de ninguna manera, pero en un escenario de subprocesos múltiples un subproceso puede estar enumerando la colección mientras otro hilo puede estar alterando al mismo tiempo.

+0

Nota: Revisé el SSCLI (Rotor) código fuente de ReadOnlyCollection antes de escribir mi respuesta, para asegurarse de que efectivamente es un decorador (envoltorio) –

+0

I segundo. Es solo un envoltorio. Bastante inútil si su colección es modificada fuera modificada por alguna otra clase. El nombre se extravía en el mundo de los hilos. – asyncwait

+0

@asyncwait gracias por su comentario, me recordó que debería agregar una enmienda a mi respuesta. –

3

Esto MSDN article staes: "Una instancia de la clase genérica ReadOnlyCollection es siempre de solo lectura.Una colección que es de sólo lectura es simplemente una colección con un envoltorio que impide la modificación de la colección "

así que creo que la iteración no es hilo de seguridad, ya que utiliza internamente una colección segura para subprocesos no normal de los objetos.

Las implicaciones son que diferentes subprocesos pueden obtener diferentes valores si de algún modo la colección cambia. Use una instrucción lock para evitar el acceso simultáneo a la colección de diferentes subprocesos al mismo tiempo.

Cuestiones relacionadas