"Si un trabajador quiere hacer bien su trabajo, primero debe afilar sus herramientas." - Confucio, "Las Analectas de Confucio. Lu Linggong"
Página delantera > Programación > ¿Por qué un subproceso siempre vuelve a adquirir el bloqueo del objeto después de notificar() o notificar a todos()?

¿Por qué un subproceso siempre vuelve a adquirir el bloqueo del objeto después de notificar() o notificar a todos()?

Publicado el 2024-11-16
Navegar:273

Why Does One Thread Always Reacquire the Object Lock After notify() or notifyAll()?

La sutil distinción entre notify() y notifyAll()

Si bien la principal diferencia entre notify() y notifyAll() radica en cantidad de subprocesos en espera que despiertan (uno contra todos), esto plantea otra pregunta:

¿Por qué un subproceso siempre vuelve a adquirir el bloqueo del objeto?

En general En este caso, tanto notify() como notifyAll() no especifican qué subproceso en espera se seleccionará para volver a adquirir el bloqueo. La JVM o el programador de subprocesos del sistema realiza esta selección, que puede no ser determinista.

La necesidad de notificar a todos()

Sin embargo, usar notify() en ciertos escenarios puede llevar a un punto muerto, como lo ilustra el siguiente ejemplo:

Clase Productor/Consumidor con notify()

public class ProducerConsumer {

    private final int MAX_SIZE = 1;  // Buffer size

    private List buf = new ArrayList();

    public synchronized void put(Object o) {
        while (buf.size() == MAX_SIZE) {
            wait();
        }
        buf.add(o);
        notify();
    }

    public synchronized Object get() {
        while (buf.size() == 0) {
            wait();
        }
        Object o = buf.remove(0);
        notify();
        return o;
    }
}

Escenario de punto muerto:

  1. El productor P1 coloca un objeto en el búfer.
  2. El productor P2 y P3 intentan colocar objetos pero no bloqueado porque el búfer está lleno.
  3. El consumidor C1 intenta obtener un objeto del búfer.
  4. C1 se está ejecutando y obtiene el objeto, luego notifica un hilo en espera.
  5. La notificación puede despertar a P2 o C2, pero ambos están bloqueados al intentar volver a adquirir el bloqueo.
  6. C3 también se bloquea al intentar adquirir el bloqueo.

Como Como resultado, los tres subprocesos están esperando indefinidamente, lo que lleva a un punto muerto.

La solución: notifyAll()

Para resolver este punto muerto, se debe usar notifyAll() en lugar de notify() en el código de productor/consumidor. Esto garantiza que todos los subprocesos en espera se activen, evitando interbloqueos.

Recomendación:

Para la mayoría de los escenarios, notifyAll() es el método preferido, ya que evita posibles interbloqueos. Si el escenario específico requiere activar solo un hilo de espera específico, entonces notify() puede usarse con precaución.

Último tutorial Más>

Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.

Copyright© 2022 湘ICP备2022001581号-3