Me di cuenta de que puede llamar a Queue.Synchronize para obtener un objeto queue seguro para subprocesos, pero el mismo método no está disponible en Queue <T>. ¿Alguien sabe por qué? Parece un poco raro.¿Por qué no hay una cola genérica sincronizada en .NET?
Respuesta
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.
(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.
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.)
hay uno ahora, en .Net 4.0:
ConcurrentQueue<T>
en System.Collections.Concurrent
- 1. ¿Por qué no hay una versión genérica de HybridDictionary?
- 2. ¿Por qué no hay una interfaz "configurada" en .NET Framework?
- 3. ¿Por qué RabbitMQ no persiste mensajes en una cola duradera?
- 4. ¿Por qué no puedo atrapar una excepción genérica en C#?
- 5. ¿Por qué no hay SortedList <T> en .NET?
- 6. ¿Por qué el framework .Net no tiene una clase de cola de prioridad?
- 7. ¿Por qué no hay CallerTypeNameAttribute en .NET 4.5?
- 8. ¿Hay lectura no sincronizada de enhebrado de enteros en java?
- 9. ¿Por qué no es esta cola recursiva?
- 10. ¿Por qué no puedo declarar una lista genérica como anulable?
- 11. ¿Por qué un PriorityQueue no actuaría como una cola?
- 12. ¿Qué significa cuando decimos que una ArrayList no está sincronizada?
- 13. ¿Por qué no hay Dictionary.TrimExcess()?
- 14. ¿Por qué no hay impulso :: copy_on_write_ptr?
- 15. ¿Existe una cola ordenada en .NET?
- 16. ¿Por qué no hay varianza genérica para las clases en C# 4.0?
- 17. Entrada de cadena no sincronizada en C++
- 18. ¿Por qué no hay clase Tree <T> en .NET?
- 19. ¿Por qué la palabra clave sincronizada en Java se llama 'sincronizada' en lugar de la más precisa 'excluida'?
- 20. ¿Por qué hay interfaces en tipos de referencia .Net?
- 21. ¿Por qué no hay ReverseEnumerator en C#?
- 22. ¡la sección sincronizada no bloquea!
- 23. ¿Por qué no hay strtoi en stdlib.h?
- 24. ¿Por qué no hay una interfaz IQueue <T> o IStack <T> en .NET Framework?
- 25. ¿Por qué .Net no tiene una estructura de datos establecida?
- 26. ¿Por qué no hay isFocused() en GWT?
- 27. por qué no hay sizeof en java
- 28. ¿Por qué no hay una variable estática local en Java?
- 29. ¿Por qué no hay una interfaz "Iterable" en el STL?
- 30. ¿Por qué no hay una función String.IsNumeric en C#
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
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 –
por qué esto es un objeto estático – Svisstack