Java ждать () / join (): почему Делает ли это не тупиковую?

Учитывая следующий код Java:

public class Test {

    static private class MyThread extends Thread {
        private boolean mustShutdown = false;

        @Override
        public synchronized void run() {
            // loop and do nothing, just wait until we must shut down
            while (!mustShutdown) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    System.out.println("Exception on wait()");
                }
            }
        }

        public synchronized void shutdown() throws InterruptedException {
            // set flag for termination, notify the thread and wait for it to die
            mustShutdown = true;
            notify();
            join(); // lock still being held here, due to 'synchronized'
        }
    }

    public static void main(String[] args) {
        MyThread mt = new MyThread();
        mt.start();

        try {
            Thread.sleep(1000);
            mt.shutdown();
        } catch (InterruptedException e) {
            System.out.println("Exception in main()");
        }
    }
}

Запуск это будет ждать одну секунду, а затем правильно выйти. Но это неожиданно для меня, я ожидаю, что тут-замок произошел здесь.

Мои рассуждения выглядят следующим образом: вновь созданная Mythread будет выполнять Run (), который объявлен «синхронизированным», так что это может позвонить в ожидании () и безопасно прочитать «нажатой); Во время этого ожидания () вызов блокировки выпускается и повторно приобретена при возврате, как описано в документации ожидания (). Через секунду после одной секунды основная тема выполняет выключение (), которое снова синхронизируется как для не доступа к набору вспомогательногодана одновременно, так как он читается другим потоком. Затем он просыпается на другой поток через Notify () и ждет для его завершения через join ().

Но на мой взгляд, нет никакого способа, чтобы другой нить мог когда-либо вернуться от ожидания (), поскольку ему необходимо повторно получить замок на объекте потока перед возвратом. Это не может сделать это, потому что выключение () все еще содержит блокировку во время соединения внутри (). Почему это все еще работает и выходит правильно?

9
задан Nathan Hughes 11 October 2017 в 20:14
поделиться