Pregunta

Noté que puedes llamar a Queue.Synchronize para obtener un objeto de cola seguro para subprocesos, pero el mismo método no está disponible en Queue<T>.¿Alguien sabe por qué?Parece un poco extraño.

¿Fue útil?

Solución

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

ConcurrentQueue<T> es una reescritura completa desde cero, 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 la API.


Según el comentario de Zooba, el equipo de BCL decidió que muchos desarrolladores no entendían bien el propósito de Synchronize (y, en menor medida, SyncRoot).

Brian Grunkemeyer describió esto en el blog del equipo de BCL hace un par de años:http://blogs.msdn.com/bclteam/archive/2005/03/15/396399.aspx

La cuestión clave es obtener la granularidad correcta en torno a los bloqueos, donde algunos desarrolladores usarían ingenuamente múltiples propiedades o métodos en una colección "sincronizada" y creerían que su código es seguro para subprocesos.Brian usa Queue como ejemplo,

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

Los desarrolladores no se darían cuenta de que otro hilo podría cambiar el recuento antes de que se invocara Dequeue.

Obligar a los desarrolladores a utilizar una declaración de bloqueo explícita 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 Sincronizado, pero también porque en muchos casos hay una mejor opción de objeto de bloqueo: la mayoría de las veces, ya sea la instancia de la cola en sí o una

private static object lockObjForQueueOperations = new object();

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

Este último enfoque suele ser el más seguro ya que evita otras trampas comunes:

Como ellos dicen, enhebrar es difícil, y hacer que parezca fácil puede resultar peligroso.

Otros consejos

Quizás valga la pena echarle un vistazo al CTP paralelo;aquí hay una entrada de blog de los chicos que lo están preparando y que es bastante actual:

Enumeración de colecciones simultáneas

No es exactamente lo mismo, pero podría resolver tu problema mayor.(Incluso usan Queue<T> versus ConcurrentQueue<T> como su ejemplo.)

Hay uno ahora, en .Net 4.0:

ConcurrentQueue<T> 

en System.Collections.Concurrent

http://msdn.microsoft.com/en-us/library/dd267265.aspx

(Supongo que te refieres a Queue<T> para el segundo).

No puedo responder específicamente a la pregunta, excepto que las propiedades IsSynchronized y SyncRoot (pero no Synchronise() 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 forma prevista por los diseñadores de la biblioteca o simplemente no se usaron lo suficiente como para justificar su conservación en las colecciones más nuevas.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top