Как wait () и notifyAll () предотвращают взаимоблокировку в данном фрагменте кода? - PullRequest
0 голосов
/ 08 февраля 2019

Вот фрагмент кода:

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 голосов
/ 08 февраля 2019

"Итак, если EvenThread сначала запустит метод waitTurn и дождется смены хода, он удерживает LOCK, OddThread НЕ может войти в метод toggleTurn"

Он удерживает LOCK только небольшой период времени, пока методwait() вызывается.Метод wait() освобождает LOCK и позволяет другому потоку войти в критическую секцию.

...