¿Los métodos de inserción y eliminación de LinkedBlockingQueue son seguros para subprocesos?

3 minutos de lectura

Estoy usando LinkedBlockingQueue entre dos hilos diferentes. Un hilo agrega datos a través de addmientras que el otro subproceso recibe datos a través de take.

Mi pregunta es, ¿necesito sincronizar el acceso a add y take. Es LinkedBlockingQueue¿Los métodos de inserción y eliminación son seguros para subprocesos?

  • Si no fueran seguros para subprocesos, entonces necesitaría sincronizarlos. Entonces, una toma () podría muy bien tomar el mutex de una cola vacía, bloqueando cualquier otro hilo para que no se agregue a él. ¡Hola punto muerto!

    – paiego

    31 de diciembre de 2019 a las 6:03

avatar de usuario
Mateo Flaschen

Sí. De los documentos:

“Las implementaciones de BlockingQueue son seguras para subprocesos. Todos los métodos de cola logran sus efectos de forma atómica mediante bloqueos internos u otras formas de control de concurrencia. Sin embargo, las operaciones de recopilación masiva addAll, containsAll, retainAll y removeAll no necesariamente se realizan de forma atómica a menos que se especifique lo contrario en una implementación. Por lo tanto, es posible, por ejemplo, que addAll(c) falle (lanzando una excepción) después de agregar solo algunos de los elementos en c”.

  • no es en realidad. No, no si solo está usando agregar y tomar, pero si usara una operación masiva, ¿tendría que sincronizarla en lugar de simplemente “Sí”? ¿O estoy leyendo mal el documento?

    – cproinger

    3 mayo 2012 a las 13:20


  • @cproinger, no, nunca tienes que sincronizarlo, siempre y cuando estés dispuesto a lidiar con addAll lanzando una excepción después de agregar un subconjunto de los elementos (o similar). Depende de cómo defina seguro para subprocesos. Tienes razón en que los métodos masivos no tienen garantía de atomicidad.

    – Mateo Flaschen

    4 de mayo de 2012 a las 0:24

  • “Entonces, es posible, por ejemplo, que addAll(c) falle (lanzando una excepción) después de agregar solo algunos de los elementos en c”. ¿No es esto un “no”?

    – Farid

    25 de junio de 2021 a las 11:23

avatar de usuario
Amrish Pandey

Sí, BlockingQueue métodos add() y take() son seguros para subprocesos pero con una diferencia.

add () y take() método utiliza 2 diferentes ReentrantLock objetos.

add() usos del método

private final ReentrantLock putLock = new ReentrantLock();

take() usos del método

private final ReentrantLock takeLock = new ReentrantLock();

Por lo tanto, el acceso simultáneo a add() el método está sincronizado. Del mismo modo, el acceso simultáneo a take() el método es synchronized.

Pero, el acceso simultáneo a add() y take() el método no es synchronized ya que están usando 2 objetos de bloqueo diferentes (excepto durante la condición de borde de la cola llena/vacía).

  • Esta respuesta hace una observación válida, pero pasa por alto que los implementadores de LinkedBlockingQueue estaban al tanto de este problema y lo abordaron. Detalles aquí: stackoverflow.com/questions/26543807/…

    – Chris K.

    24 de octubre de 2014 a las 8:39

  • Sí estoy de acuerdo. LInkedBlockingQueue ofrece mejor simultaneidad que ArrayBlockingQueue y mantiene la seguridad de subprocesos al sincronizar solo la condición de borde. Los métodos de inserción y eliminación se han sincronizado de forma inteligente solo para casos extremos

    – Amrish Pandey

    24 de octubre de 2014 a las 8:43

  • Esta respuesta es incorrecta. add y take son seguros para subprocesos y se pueden usar simultáneamente sin sincronización adicional.

    – es

    19/01/2016 a las 17:30

  • Corregido mi respuesta. Los agregados y retiros simultáneos no están sincronizados, excepto durante la condición de borde de la cola llena/vacía.

    – Amrish Pandey

    20 de enero de 2016 a las 3:48

  • Creo que la respuesta es confusa. Creo que incluso cuando no están sincronizados, siguen siendo seguros y no hay necesidad de sincronizarlos manualmente.

    – Suma

    19 junio 2019 a las 15:40

Simplemente sí, definitivamente es seguro para subprocesos; de lo contrario, no habría calificado como candidato para almacenar elementos para ThreadPoolExecutor.

Simplemente agregue y recupere el elemento sin preocuparse por la concurrencia de BlockingQueue.

  • Solo se anuncia como seguro para subprocesos, en realidad los documentos dicen “Entonces, es posible, por ejemplo, que addAll(c) falle (lanzando una excepción) después de agregar solo algunos de los elementos en c”.

    – Farid

    25 de junio de 2021 a las 11:25

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad