2010-06-05 5 views
63

Cuál es la norma hoy en día cuando se necesita una recogida segura de rosca (por ejemplo Set). ¿Lo sincronizo yo mismo o hay una colección intrínsecamente segura para subprocesos?de rosca en .NET

+6

¿Seguro para qué operaciones? –

+2

@John, ya sabes, agregando, leyendo etc ... algo así como las colecciones simultáneas de Java. – ripper234

+1

debe actualizar su pregunta con esta información. Hace una gran diferencia que desee colecciones que sean seguras para todo, frente a una colección que, por ejemplo, es segura para subprocesos solo para inserción. –

Respuesta

94

El Marco .NET 4.0 presenta varias colecciones de hilo de seguridad en el System.Collections.Concurrent Namespace:

ConcurrentBag<T>
      representa una, colección desordenada thread-safe de los objetos.

ConcurrentDictionary<TKey, TValue>
    representa una colección thread-safe de pares de valores clave que se puede acceder por múltiples hilos simultáneamente.

ConcurrentQueue<T>
    representa una primera colección thread-safe en-primero en salir (FIFO).

ConcurrentStack<T>
    representa un último hilo-caja fuerte en la primera a cabo la recogida (LIFO).


Otras colecciones en .NET Framework no se Hilo de seguridad por defecto y necesitan ser bloqueado para cada operación:

lock (mySet) 
{ 
    mySet.Add("Hello World"); 
} 
+3

Puede preferir utilizar ReaderWriterLockSlim al crear una colección segura para subprocesos. – SandRock

4

.NET 4 proporciona un conjunto de colecciones de rosca-safe bajo System.Collections.Concurrent

17

Pre .NET 4.0 mayoría de las colecciones en .Net no es seguro para subprocesos. Vas a tener que hacer un poco de trabajo usted mismo para manejar la sincronización: http://msdn.microsoft.com/en-us/library/573ths2x.aspx

Presupuesto de artículo: Hilo de segura utilizando cualquiera de los métodos siguientes

clases Colecciones se pueden hacer:

Crear una envoltura thread-safe usando el método sincronizado , y accede a la colección exclusivamente a través de que envoltura.

Si la clase no tiene un método sincronizada, se derivan de la clase e implementar un método sincronizado utilizando la propiedad SyncRoot.

utilizar un mecanismo de bloqueo, tales como la declaración bloqueo en C# (SyncLock en Visual Basic), en la propiedad SyncRoot cuando se accede a la colección .

Sync Root Property
Lock Statement

Object thisLock = new Object(); 
...... 
lock (thisLock) 
{ 
    // Critical code section 
} 

En.neto 4.0 del introdujo el System.Collections.Concurrent espacio de nombres

Blocking Collection
Concurrent Bag
Concurrent Queue
Concurrent Dictionary
Ordable Partitioner
Partitioner
Partitioner T

+4

El objeto que está bloqueando debe ser una variable de instancia; de lo contrario, no tiene sentido porque siempre está bloqueando una nueva referencia. – Femaref

+1

Eso es verdad. Este es solo un ejemplo que se encontraba en la página de MSDN sobre cómo se usa el código de bloqueo. – kemiller2002

1

En una adición a las clases muy útiles en System.Collections.Concurrent, una técnica estándar en la mayoría -read-rare-change sc enarios (o si hay, sin embargo, escrituras frecuentes, pero no simultáneas) que también se aplica a .Net se llama Copy-on-write.

Tiene un par de propiedades que son deseables en los programas altamente concurrentes:

  • casos de recogida de objetos sí mismos son inmutables (es decir, hilo de seguridad, se pueden enumerar de forma segura sin bloqueo)
  • modificación pueden tomar todo el tiempo que quiera, el rendimiento y la concurrencia de las lecturas no se ven afectados
  • puede haber implemented generically para convertir cualquier estructura de datos que no es seguro para subprocesos en uno que es

Limitación: si hay escrituras concurrentes, las modificaciones pueden tener que volverse a intentar, de modo que cuanto más escrituras concurrentes obtengan, menos eficiente será. (Eso es optimistic concurrency en el trabajo)

comentario Editar Scott Chamberlain me recordó que hay otra limitación: Si sus estructuras de datos son enormes, y las modificaciones ocurren a menudo, una copia-todo-en-escritura podría ser prohibitivo en términos de consumo de memoria y el costo de copia de la CPU involucrados.

+0

Microsoft proporciona un conjunto de colecciones de copia sobre escritura a través de NuGet a través de [Microsoft.Bcl.Immutable] (https://www.nuget.org/packages/Microsoft.Bcl.Immutable), puede encontrar más información [aquí] (http://blogs.msdn.com/b/bclteam/archive/2012/12/18/preview-of-immutable-collections-released-on-nuget.aspx) –

+0

@ScottChamberlain Los suyos son mucho más sofisticados que mi simple , pero genérico, enfoque de "copiar todo al escribir", ya que solo copian parte de los datos. Por lo tanto, se pueden usar incluso cambiando enormes estructuras de datos, que serán ineficientes con copy-all-on-write, tanto en términos del costo de copia de la CPU como del consumo de memoria para almacenar múltiples copias completas en la memoria. –

Cuestiones relacionadas