2012-05-01 18 views
5

¿No es posible que se llame a notify() en otro subproceso antes de wait() en un subproceso? Me está sucediendo a mí.Java notify() se llama antes de wait()

Un cliente solicita un valor de un objetivo y espera una variable de resultado RV. En caso de que el objetivo sea el cliente en sí, actualizo RV con el resultado correcto y llamo a notify() en RV en otro hilo.

class EMU { 

    ResultVar RV; 
    Address my_address; 

    ResultVar findValue(String key) { 
    String tgt = findTarget(key); 
    sendRequest(tgt, key); 
    synchronized(RV) { 
     RV.wait(); 
    } 

    return RV; 
    } 

    Runnable Server = new Runnable() { 
    public void run() { 
     //code to receive connections. Assume object of type Request is read from the stream. 
     Request r = (Request) ois.readObject(); 
     if(r.requesterAddr.compareTo(my_address) == 0) { 
     String val = findVal(key); 
     RV.putVal(val); 
     synchronized(RV){ 
      RV.notify(); 
     } 
     } 
    } 
    }; 
} 

El problema es que antes de que el solicitante ha completado todos los "redes" (sendReqest en el ejemplo anterior) con ella misma, el resultado se actualiza en la variable de resultado. Cuando el hilo del solicitante ahora llama a wait(), el programa no continúa, ya que se ha llamado a notify.

¿Cómo podemos prevenirlo?

+1

'En caso de que el objetivo es que el cliente itself' ¿Qué quiere decir aquí? ¿Puedes poner algo de código de muestra? – Cratylus

+1

@shishir garg podría pegar algún código –

+0

Sin ver el código es difícil de responder - 2 comentarios sin embargo: a) en general es mejor utilizar notificar todo en lugar de notificar, a menos que sepa lo que está haciendo b) usando esperar y notificar puede ser propenso a errores y debe usar la API de concurrencia de mayor nivel a menos que necesite algo muy específico. – assylias

Respuesta

4

Nada detiene llamando notify en un objeto que no está siendo wait cado por otro hilo.

Parece que lo que quiere es esperar solo si se cumple alguna condición. Por ejemplo:

synchronized (results) { 
    while (!results.hasResults()) { 
     // no results yet; wait for them 
     try { 
      results.wait(); 
     } catch (InterruptedException ie) { /* ignore */ } 
    } 
} 
1

Recomiendo encarecidamente que no se reinvente la rueda.

La interfaz Future de Java está diseñada para resultados que solo pueden llegar más tarde, y la clase FutureTask implementa esta interfaz.

Haz que el primer hilo obtenga acceso al futuro y obtén el segundo hilo para ejecutar FutureTask, y todo esto se maneja por ti. También obtienes soporte de tiempo de espera de forma gratuita.

0

Uso alguna condición antes de ir a wait() y asegúrese de que la condición es seguro para hilos :)

class EMU{ 
    ResultVar RV; 
    Address my_address; 
    volatile boolean condition = true; 

    ResultVar findValue(String key){ 
     String tgt = findTarget(key); 
     sendRequest(tgt, key); 
     synchronized(RV){ 
      while(condition == true) 
      { 
       RV.wait(); 
      } 
     } 
     return RV; 
    } 

    Runnable Server = new Runnable(){ 
     public void run(){ 
      //code to receive connections. Assume object of type Request is read from the stream. 
      Request r = (Request) ois.readObject(); 
      if(r.requesterAddr.compareTo(my_address) == 0){ 
       String val = findVal(key); 
       RV.putVal(val); 
       synchronized(RV){ 
        condition = false; 
        RV.notify(); 
       } 
      } 
     } 

    }; 
Cuestiones relacionadas