1

このコードがデッドロックである理由を誰か説明してください。正常に動作するはずです。詳しく説明してください。ありがとう。

public class H extends Thread {
    String info = "";
    public H (String info) {
        this.info = info;
    }

    public synchronized void run() {
        try {
            while (true) {
                System.out.println(info);
                notify();
                wait();
            }
        } catch (Exception e) {}

    }
    public static void main(String[] args) {
          new H("0").start();
          new H("1").start();
    }

}

4

3 に答える 3

5

各スレッドは、this(メソッドのキーワードを介してsynchronized) 同期しますが、これは 2 つのスレッド オブジェクトごとに異なります。それらはそれぞれ呼び出しますがnotify、異なるwaitため相互作用しませんthis。そのため、最初の繰り返しでwaitは、誰も起こしてくれる人がいないため、呼び出しとブロックの両方が永久に行われます。

コードを意図したとおりに機能させるために行った変更を次に示します。スレッドの通信を可能にする共有静的フィールドに注意してください。

public class Test extends Thread {
    String info = "";
    static final Object signal = new Object();
    static volatile String current = null;

    public Test (String info) {
        this.info = info;
    }

    public void run() {
        try {
            synchronized(signal) {
                while (true) {                                  
                    while(current.equals(info))
                        signal.wait();
                    System.out.println(info);
                    current = info;
                    signal.notify();
                }
            }
        } catch (Exception e) {}

    }

    public static void main(String[] args) {
        Test.current = "0";
        new Test("0").start();
        new Test("1").start();
    }
}

私が作成したかった元のコードには、他にもいくつかのメモがあります。

  • Runnableを拡張するのではなく、実装するようにしてくださいThread。そうすることで、柔軟性が高まります。
  • 例外を飲み込まないでください。
于 2012-10-21T18:17:44.693 に答える
3

notifyとは異なるオブジェクトでwait呼び出されるため、スレッドが に到達すると、他のスレッドはそれに通知せず、代わりに各スレッドがそれ自体に通知します。Threadwait

フローは大まかに次のとおりです (インターリーブがある場合があります)。

  1. スレッド A の開始
  2. ThreadA は、ThreadA のロックを待機しているオブジェクトを通知します
  3. ThreadA は ThreadA のロックを待機します
  4. スレッド B の開始
  5. ThreadB は、ThreadB のロックを待機しているオブジェクトを通知します
  6. ThreadB は ThreadB のロックを待機します

最終状態 - 両方のスレッドが待機しており、誰も通知しません。

于 2012-10-21T18:18:18.247 に答える
1

notify() は、現在オブジェクトを待機しているスレッドのみを起こします。notify() を呼び出すと、どちらの場合も待機しているスレッドはありません。次に、wait を呼び出すと、notify() のコードはまったくありません。基本的に、待機している必要があるため、同じスレッドからスレッドに通知することはできません。しばらく待ってからメインスレッドから通知してみて、何が起こるかを確認してください。

public class H extends Thread {
    String info = "";
    public H (String info) {
        this.info = info;
    }

    public synchronized void run() {
        try {
            while (true) {
                System.out.println(info);
                wait();
            }
        } catch (Exception e) {}

    }
    public static void main(String[] args) throws Exception {
          H a = new H("0").start();
          H b = new H("1").start();
          Thread.sleep(1000);
          a.notify();
          b.notify();
    }
}

どちらのスレッドも他方に通知しないことに注意してください。オブジェクトの待機は、クラス全体ではなく、オブジェクトのみを待機します。

TL;DR: notify() は何も実行せず、wait() はデッドロックを作成します。

于 2012-10-21T18:18:16.563 に答える