2008-09-20 18 views

Respuesta

52

actualización - en .NET 4, ahora hay ConcurrentQueue<T> en System.Collections.Concurrent, tal como se documenta aquí http://msdn.microsoft.com/en-us/library/dd267265.aspx. Es interesante observar que su método IsSynchronized (con razón) devuelve false.

ConcurrentQueue<T> es una reescritura completa, que crea copias de la cola para enumerar y utiliza técnicas avanzadas sin bloqueo como Interlocked.CompareExchange() y Thread.SpinWait().

El resto de esta respuesta sigue siendo relevante en la medida en que se relaciona con la desaparición de los antiguos miembros Synchronize() y SyncRoot, y por qué no funcionaron muy bien desde la perspectiva de una API.


De acuerdo con el comentario de Zooba, el equipo BCL decidió que muchos desarrolladores han malentendido el propósito de Sincronizar (y en menor medida, SyncRoot)

Brian Grunkemeyer describen esto en el equipo BCL un blog un par de años atrás: http://blogs.msdn.com/bclteam/archive/2005/03/15/396399.aspx

la cuestión clave es conseguir la granularidad correcta alrededor de cerraduras, donde algunos desarrolladores podrían utilizar ingenuamente múltiples propiedades o métodos en una colección "sincronizado" y creen que su código sea hilo de seguridad. Brian utiliza cola como ejemplo,

if (queue.Count > 0) { 
    object obj = null; 
    try { 
     obj = queue.Dequeue(); 

Los desarrolladores no se daría cuenta de que Contador podría ser cambiado por otro subproceso antes de quitar de la cola se invocó.

Obligar a los desarrolladores a utilizar una instrucción de bloqueo explícito en toda la operación significa evitar esta falsa sensación de seguridad.

Como menciona Brian, la eliminación de SyncRoot se debió en parte a que se había introducido principalmente para admitir Synchronized, pero también porque en muchos casos hay una mejor opción de objeto de bloqueo: la mayoría de las veces, la instancia de Queue en sí misma. o una

private static object lockObjForQueueOperations = new object(); 

de la clase propietaria de la instancia de la cola ...

Este último enfoque es por lo general más segura, ya que evita las otras trampas comunes:

Como se suele decir, threading is hard, y hacer que parezca fácil puede ser peligroso.

+0

No estoy de acuerdo con su consejo. Es interesante que la documentación de bloqueo de MSDN dice: "Normalmente, la expresión será esta" http://msdn.microsoft.com/en-us/library/c5kehkcz%28VS.71%29.aspx – dvogel

+2

Sí, lo entendieron mal. NET 1.1 doco, consulte la última versión de .NET 4 para las correcciones ... http://msdn.microsoft.com/en-us/library/c5kehkcz(v=VS.100).aspx –

+0

por qué esto es un objeto estático – Svisstack

0

(supongo que te refieres cola <T> para la segunda.)

No puedo responder a la pregunta específica, excepto que las propiedades IsSynchronized y SyncRoot (pero no Sincronizar() explícitamente) se heredan de la interfaz ICollection. Ninguna de las colecciones genéricas usa esto y la interfaz ICollection <T> no incluye SyncRoot.

En cuanto a por qué no está incluido, solo puedo especular que no se usaron de la manera prevista por los diseñadores de la biblioteca o simplemente no se usaron lo suficiente como para justificar su retención en las colecciones más nuevas.

7

Puede que le interese el Parallel CTP; aquí está una entrada de blog de los chicos que están poniendo juntos Eso es bastante tópica:

Enumerating Concurrent Collections

No es exactamente lo mismo, pero podría resolver su problema más grande. (Incluso utilizan Queue<T> frente ConcurrentQueue<T> como su ejemplo.)

Cuestiones relacionadas