2012-05-01 7 views
5

あるスレッドでwait()の前に別のスレッドのnotify()が呼び出される可能性はありますか? それは私と一緒に起こっている。wait()の前にJavaのnotify()が呼び出される

クライアントは、ターゲットから値を要求し、結果変数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を使うのが一般的です。 notifyはエラーが発生しやすく、非常に具体的なものを必要としない限り、より高いレベルの並行処理APIを使用する必要があります。 – assylias

答えて

4

何もあなたが別のスレッドによってwait編されていないオブジェクトにnotifyを呼び出して停止しません。

これは、何らかの条件が成立している場合にのみ待機するように思えます。例:

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

ホイールを再発明しないことを強く推奨します。

JavaのFutureインターフェイスは、後で到着する可能性のある結果用に設計されており、FutureTaskクラスはこのインターフェイスを実装しています。

最初のスレッドにFutureへのアクセス権を取得し、FutureTaskを実行する2つ目のスレッドを取得させ、これらのすべてが処理されるようにします。また、無料のタイムアウトサポートも受け取ります。

0

は(待つために行く前に、いくつかの条件を使用)し、条件がスレッドセーフであることを確認してください:)

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

    }; 
関連する問題