如何用wait()和notifyAll()防止给定代码段中的死锁?

时间:2019-02-08 07:53:36

标签: java concurrency wait deadlock notify

这是代码段:

public class PrintEvenOdd 

  public static class SynchronizedThreadMonitor {
    public final static boolean ODD_TURN = true;
    public final static boolean EVEN_TURN = false;
    private boolean turn = ODD_TURN;

    public synchronized void waitTurn(boolean oldTurn) {
        while (turn != oldTurn) {
            try {
                wait();
            } catch (InterruptedException e) {
                System.out.println("InterruptedException in wait(): " + e);
            }
        }
    }

    public synchronized void toggleTurn(){
        turn ^= true;
        notify();
    }
}

public static class OddThread extends Thread {
    private final SynchronizedThreadMonitor monitor;

    public OddThread(SynchronizedThreadMonitor monitor) {
        this.monitor = monitor;
    }

    @Override
    public void run() {
        for (int i=1; i<=100; i+=2) {
            monitor.waitTurn(SynchronizedThreadMonitor.ODD_TURN);
            System.out.println("i= " + i);
            monitor.toggleTurn();
        }
    }
}

public static class EvenThread extends Thread {
    private final SynchronizedThreadMonitor monitor;

    public EvenThread(SynchronizedThreadMonitor monitor) {
        this.monitor = monitor;
    }

    @Override
    public void run() {
        for (int i=2; i<=100; i+=2) {
            monitor.waitTurn(SynchronizedThreadMonitor.EVEN_TURN);
            System.out.println("i= " + i);
            monitor.toggleTurn();
        }
    }
}

public static void main(String[] args) throws InterruptedException {
    SynchronizedThreadMonitor monitor = new SynchronizedThreadMonitor();
    Thread t1 = new OddThread(monitor);
    Thread t2 = new EvenThread(monitor);
    t1.start();
    t2.start();
    t1.join();
    t2.join();
}

}

使用2个线程打印数字。一个打印奇数,另一个打印偶数。

据我了解,waitTurn和toggleTurn都共享该实例的相同LOCK。因此,如果一个按住LOCK,则另一种方法将无法运行。因此,如果EvenThread首先调用waitTurn方法并等待转弯,它会保持LOCK,那么OddThread将无法进入toggleTurn方法并设置转弯。据我了解,这将导致僵局。但这没有发生。

有人可以解释为什么没有发生僵局吗?

1 个答案:

答案 0 :(得分:0)

“因此,如果EvenThread先运行waitTurn方法并等待转弯,它会保持LOCK,OddThread无法进入toggleTurn方法”

它仅将LOCK保持一小段时间,直到调用方法wait()为止。方法wait()释放LOCK,并允许另一个线程进入关键部分。