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方法上的关键字),这对于两个线程对象中的每一个都是不同的。他们每个人都打电话notifywait但他们不互动,因为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上调用Thread,所以当一个线程到达时wait,另一个线程不会通知它,而是每个线程通知自己。

流程差不多(可能有交错):

  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 回答