2009-05-06 23 views

Respuesta

6

Es completamente normal. Solo puede notificar a todos los que esperan en un solo monitor. Todos los demás no están interesados. El objeto al que llama notifyAll es solo el monitor en el que están esperando otros. Si nadie está esperando nadie debe ser notificado

8

Como puede ver aquí, la llamada a notifyAll() en un objeto que no está en espera no tiene ningún efecto.

alt text

+0

No podría ser estrictamente correcto para poner un hilo de esperar a que se ejecuta en notifyAll o por lo menos no sin la advertencia de que la primera cosa que un hilo notificado hace es regrab el bloqueo del monitor. Y dado que solo uno de los hilos notificados puede atraparlo, los otros serán bloqueados. Pero bloquear no es lo mismo que esperar porque el hilo bloqueado no necesita otra señal de notify(). –

1

Sólo espera recibir una notificación objetos. Object.wait() bloquea hasta que se agote el tiempo de espera o notifique, por lo que la pregunta sigue siendo ¿cómo o por qué piensas que los objetos que no están en espera recibirán alguna notificación? no tiene sentido.

+0

Los objetos no esperan o son notificados, los hilos sí. Y es perfectamente posible y normal llamar a notifyAll() en un objeto de monitor sin saber si hay hilos esperando en él. Por ejemplo, en un escenario de productor/consumidor con una cola, el consumidor podría haber vaciado la cola y aún estar ocupado con el procesamiento cuando el productor agrega un nuevo elemento a la cola y notifica a todos los consumidores que están esperando (es decir, ninguno) sobre esto. –

+0

Eliminé el hilo para mantener las cosas lo más simples posible. –

2

El objeto está "en espera", sin esperar. El hilo es el que está esperando. Si nadie está esperando, nadie se despertará y nada especial sucederá.

+0

¿Qué sucede cuando se activa una alarma pero no hay nadie para escucharla? –

2

Situación perfectamente normal.

Digamos que tiene una cola con una cadena de producción que pone elementos en ella y una cadena de consumidores quitando elementos de ella.

Ahora el consumidor podría haber vaciado la cola y aún estar ocupado con el procesamiento, por lo que nadie está esperando a que la cola quede vacía. Ahora el productor agrega un nuevo elemento a la cola. Él tiene que llamar a notifyAll() para despertar al consumidor si estuviera esperando. Agregar lógica adicional para verificar si alguien está esperando y solo llamar a notifyAll() en ese caso agregaría una complejidad considerable (y propensa a fallas) al escenario - es mucho más fácil simplemente llamar a notifyAll() todo el tiempo.

1

Es posible que solo esté cortando pelos ;-) Puede que no sea estrictamente correcto pensar que los hilos pasen del estado "en espera" al estado "en ejecución" en notifyAll; al menos no sin la advertencia de que lo primero que hace un hilo notificado es volver a grabar el bloqueo del monitor. Y dado que solo uno de los hilos notificados puede capturarlo, los otros serán bloqueados. BLOCKED (Thread.State.Blocked) es el estado del subproceso. Pero el bloqueo es , no es lo mismo que esperar porque el hilo bloqueado no necesita otra señal de notify() para reanudar. [Bueno, sé de los despertadores espurios, pero tal vez lo contrario también podría ser cierto para algunas implementaciones de JVM: ¿una notificación perdida?]

public class HellBoy { 
    public static class MyThread extends Thread { 
     static final public Object sharedLock = new Object(); 

     public void run() { 
      synchronized (sharedLock) { 
       System.out.println("Gonna wait..."); 
       try { 
        sharedLock.wait(); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
       System.out.println("Woken up but sleeping with the lock"); 
       try { 
        Thread.sleep(2500); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
       System.out.println("exiting and unlocking"); 
      } 
     } 
    } 

    public static void main(String[] args) throws Exception { 
     new MyThread().start(); 
     new MyThread().start(); 
     new MyThread().start(); 
     new MyThread().start(); 
     Thread.sleep(200); 
     synchronized (MyThread.sharedLock) { 
      MyThread.sharedLock.notifyAll(); 
     } 
    } 
} 
+0

¿Se puede perder una notificación? –