2016-11-21 11 views
0

私は教授から与えられた書籍の試験のために勉強しています。スレッドと同期を扱うこのコードがあります:状態が変わるたびに状態変化を逃すことなく)。notifyとnotifyAllのコード/同期(理解するためのヘルプ)

public class C { 

    private int state = 0; // the state 
    private boolean modified = false; // to show if the state was changed since actualization 

    public synchronized void printNewState() { 
     while (true) { 
      if (!modified) { 
       wait(); 
      } 
      System.out.println(state); 
      modified = false; 
      notify(); 
     } 
    } 

    public synchronized void setValue(int v) { 
     if (modified) { 
      wait(); 
     } 
     state = v; 
     notify(); 
     modified = true; 
     System.out.println("value set"); 
    } 
} 

そして、それが書かれています:メソッドSetValue(int型)で
しかし、(通知することを保証するものではありませんが)printNewStateスレッドをウェイクアップ! Javaでは我々はのnotifyAll(の助けを借りて、この問題 を解決)し、少しビジーウェイト取る:を通知し、なぜ私は理解していない

public synchronized void printNewState() { 
    while (true) { 
     while (!modified) { 
      wait(); 
     } 
     System.out.println(state); 
     modified = false; 
     **notify();** \\(?) 
    } 
} 

public synchronized void setValue(int v) { 
    while (modified) { 
     wait(); 
    } 
    state = v; 
    notifyAll(); 
    modified = true; 
    System.out.println("value set"); 
} 

も)(のnotifyAllに変更されませんでしたか?この通知がsetValue(int)のスレッドに送られることは保証されないかもしれません???

notifyAll()方法は、すべての待機中のスレッドをウェイクアップするのに対し、 notify()方法は、単一待機中のスレッドをウェイクアップします

答えて

0

ありがとうございます。問題は、notify()を使用すると、目を覚ましたスレッドが効果的にランダムになります。

他のスレッドが誤ってまたは悪意を持って同じオブジェクトに入っている場合、目を覚ますスレッドの代わりに通知を受け取る可能性があります。

さらに詳しい情報はthis answerをご覧ください。その答えに対するコメントもかなり面白いです。あなたが投稿のサンプルコードで

EDIT

printNewState()内の最初notify()は、一度に1つだけの更新を扱うことができるので、その更新情報を投稿するすべて待機中のスレッドに通知しても意味がありません。 。ただし、このコードでは、setValue(int)を呼び出すスレッドだけが待機していると仮定しています。

public synchronized void setValue(int)は、本質的にはメソッドの1行目としてsynchronized(this)を持つものと同じですが、実際には保証されません。 Cクラスのインスタンスへの参照を持つコードは、それを待ってコードをスクリューアップすることができます。

同期および待機/通知アクションは、オブジェクトのロック/モニタで実行する必要があります。 private final Object monitor = new Object()synchronized(this.monitor)this.monitor.wait()this.monitor.notifyAll()など

私も、そうでない場合は、他の待機中の更新スレッドがprintNewState()が更新を気付かずに続行され、modified = trueニーズがsetValue(int)notifyAll()の前に置かれることに注意したいと思います。

また、private boolean modifiedは、実際にはprivate volatile boolean modifiedであり、private int stateでも同じですが、AtomicIntegerが最適なオプションかもしれません。

+0

ちょっとGrexis、私は質問を編集しました、残念です。私はあなたの答えに興味があるtho。 – ovoxo

+0

@ovoxo、私の編集を参照してください。 tl; drは、notifyAll()の代わりに 'notify()'がスレッドの更新だけが待っていると確信している限り意味があります。 – Grexis

+0

あなたの答えは非常にありがとう、それは多くの助け:) – ovoxo

関連する問題