Java notify()在wait()之前被调用

问题描述:

另一个线程中的notify()在一个线程中的wait()之前被调用吗? 这发生在我身上。Java notify()在wait()之前被调用

客户端从目标请求值并等待结果变量RV。 如果目标是客户端本身,我用正确的结果更新RV,并在另一个线程的RV上调用notify()。

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(); 
     } 
     } 
    } 
    }; 
} 

的问题是,请求者已经完成所有的“网络”(sendReqest在上面的例子)与自身之前,其结果是在结果变量更新。当请求者线程现在调用wait()时,程序不会继续,因为notify已经被调用。

我们该如何预防?

+1

'如果目标是itself'你的意思是这里的客户端的一些情况?你可以把一些代码示例? – Cratylus

+1

@shishir garg能否请你粘贴一些代码 –

+0

没有看到代码就很难回答 - 尽管有2条评论:a)通常使用notifyAll比通知更好,除非你知道你在做什么b)使用wait和通知可能容易出错,您应该使用更高级别的并发API,除非您需要非常具体的东西。 – assylias

你等待(在一个循环中)之前检查一些标志,请参阅教程:http://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html

我们无法阻止你,不是被wait被另一个线程编的对象上调用notify

这听起来像你想要的只是一个等待,如果一些条件成立。例如:

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

我强烈建议不要重新发明车轮。

Java的Future接口是专门为可能会晚到的结果而设计的,并且FutureTask类实现此接口。

让第一个线程获得对Future的访问权并获得第二个线程来运行FutureTask,并且所有这些东西都可以为您处理。您也可以免费获得超时支持。

使用之前要等待(),并确保该条件是线程安全的:)

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(); 
       } 
      } 
     } 

    };