Java中的多线程死锁

时间:2012-10-21 18:13:00

标签: java multithreading

拜托,有人可以解释一下为什么这段代码是僵局。它似乎应该正常工作。请详细解释。感谢。

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

}

3 个答案:

答案 0 :(得分: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。它为您提供了更多的灵活性。
  • 不要吞下例外。

答案 1 :(得分:3)

notifywait在不同的Thread对象上调用,因此当一个线程到达wait时,另一个线程将不会通知它,而是,每个线程都会通知自己。

流程非常多(可能存在交错):

  1. ThreadA启动
  2. ThreadA通知正在等待ThreadA锁定的对象
  3. ThreadA等待ThreadA的锁定
  4. ThreadB启动
  5. ThreadB通知正在等待ThreadB锁定的对象
  6. ThreadB等待ThreadB的锁定
  7. 最终状态 - 两个线程都在等待,没有人通知它们。

答案 2 :(得分:1)

notify()仅唤醒当前正在等待该对象的线程。当你调用notify()时,在任何一种情况下都没有线程在等待。然后,当你调用wait时,你永远不会有任何通知()的代码。基本上,您无法从同一个线程通知线程,因为它必须等待。在等待一段时间之后尝试通过主线程通知它们,看看会发生什么。

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()创建了死锁。