Estaba revisando el código fuente de ArrayBlockingQueue y LinkedBlockingQueue. LinkedBlockingQueue tiene un putLock y un takeLock para insertar y eliminar, respectivamente, pero ArrayBlockingQueue usa solo 1 bloqueo. Creo que LinkedBlockingQueue se implementó según el diseño descrito en Simple, Fast, and Practical Non-Blocking and Blocking Concurrent Queue Algorithms. En este documento, mencionan que mantienen un nodo ficticio para que los enqueuers nunca tengan que acceder a la cabeza y los dequeuers nunca tengan que acceder a la cola, lo que evita los escenarios de interbloqueo. Me preguntaba por qué ArrayBlockingQueue no toma prestada la misma idea y usa 2 bloqueos en su lugar.ArrayBlockingQueue utiliza un único bloqueo para la inserción y eliminación, pero LinkedBlockingQueue utiliza 2 bloqueos separados
Respuesta
ArrayBlockingQueue tiene que evitar sobrescribir las entradas para que sepa dónde están el inicio y el final. Un LinkedBlockQueue no necesita saber esto, ya que le permite al GC preocuparse por limpiar los Nodos en la cola.
Me preguntaba por qué ArrayBlockingQueue no toma prestada la misma idea y usa 2 cerrojos en su lugar.
Porque el ArrayBlockingQueue
utiliza una estructura de datos mucho más simple para contener los elementos de la cola.
El ArrayBlockingQueue
almacena sus datos en una matriz private final E[] items;
. Para que varios hilos se ocupen de este mismo espacio de almacenamiento, ya sea al agregarlos o eliminarlos, tienen que usar el mismo bloqueo. Esto no solo se debe a la barrera de la memoria sino a la protección de exclusión mutua, ya que están modificando la misma matriz.
LinkedBlockingQueue
por el otro lado es una lista vinculada de elementos de cola que es completamente diferente y permite la posibilidad de tener un doble bloqueo. Es el almacenamiento interno de los elementos en la cola que habilitó las diferentes configuraciones de bloqueo.
Creo que es posible que ABQ tome prestada la misma idea que LBQ. Consulte mi código http://pastebin.com/ZD1uFy7S y una pregunta similar que hice en SO ArrayBlockingQueue: concurrent put and take.
La razón por la que no lo usaron, se debe principalmente a la complejidad en la implementación, especialmente los iteradores, y el intercambio entre la complejidad y el rendimiento no fue tan lucrativo.
Para obtener más información, echa un vistazo a http://jsr166-concurrency.10961.n7.nabble.com/ArrayBlockingQueue-concurrent-put-and-take-tc1306.html.
Se usan 2 bloqueos en LBQ para restringir el acceso a la cabeza y al bloqueo al mismo tiempo. El bloqueo del cabezal no permite que dos elementos se eliminen al mismo tiempo y el bloqueo de cola no permite que dos elementos se agreguen simultáneamente a la cola. los dos cierres juntos evitan las carreras.
- 1. ¿Los pasos de inserción y eliminación de LinkedBlockingQueue son seguros?
- 2. nginx: ¿Es multiproceso pero utiliza múltiples procesos?
- 3. ¿Para qué se utiliza la reentrada de bloqueo en java?
- 4. ¿Por qué ArrayBlockingQueue se llama una cola limitada mientras que LinkedBlockingQueue se llama cola de bloqueo ilimitada?
- 5. ¿Utiliza AOP? ¿y para qué?
- 6. ¿Utiliza los enlaces múltiples de Indy Server como sockets separados?
- 7. (objeto) es un 'campo', pero se utiliza como un 'tipo'
- 8. Archivo de bloqueo y eliminación
- 9. ¿Para qué se utiliza Sqlite?
- 10. Symfony 2 - Sluggable no define si se utiliza la forma
- 11. ¿Utiliza NSArray para especificar otherButtonTitles?
- 12. La invocación de un método que utiliza la reflexión sobre un objeto único
- 13. ¿Utiliza Auto y Lambda para manejar la señal?
- 14. ¿Utiliza llaves para un alcance adicional?
- 15. ¿Utiliza la sesión cookies?
- 16. ¿Utiliza Delphi para aprovechar la tecnología GPGPU?
- 17. ¿Utiliza MEF para importar un WPF DataTemplate?
- 18. ¿Para qué se utiliza LDAP?
- 19. ¿Para qué se utiliza nbactions.xml?
- 20. ¿Utiliza NSSet hash para definir la exclusividad?
- 21. ¿Utiliza Phing?
- 22. ¿Utiliza un archivo setParameters.xml diferente?
- 23. ¿Para qué se utiliza .data.rel.ro?
- 24. ¿Para qué se utiliza la sección COMDAT?
- 25. ¿para qué se utiliza java.lang.reflect.Method.isBridge()?
- 26. ¿para qué se utiliza ids.xml?
- 27. utiliza para el alcance dinámico?
- 28. aplicación Android utiliza la toma para enviar y recibir mensajes:
- 29. ¿Utiliza aserciones?
- 30. ¿Utiliza Plastic SCM para pequeños proyectos personales?
Gracias por apuntarme en la dirección correcta. Revisé nuevamente el código y encontré que tanto ArrayBlockingQueue como LinkedBlockingQueue mantienen la variable "count". Esto es AtomicInteger en LinkedBlockingQueue (incrementado y decrementado en consecuencia en put y remove) y un int en ArrayBlockingQueue. Y supongo que no puede ser un AtomicInteger en ArrayBlockingQueue porque tiene que envolverse. – user1168577
@Peter sería realmente grandioso si pudiera explicar por qué el algoritmo Two Quech Algorithm no funcionaría. count puede ser AtomicInteger en el caso de ABQ, y la anulación puede evitarse contando chechking == max_capacity. – veritas
@veritas ¿Puede explicar dónde menciono el algoritmo de cola de dos cerraduras? Escribí esto hace dos años y no puedo encontrar lo que estás hablando. –