Игры синхронизации Java: синхронизированы && wait && notify - PullRequest
3 голосов
/ 17 декабря 2009

Я из мира .NET и, к сожалению, ищу источник Java глазами .NET.

Следующий код взят из приложений для Android (но не для Android):

    private class Worker implements Runnable {
        private final Object mLock = new Object();
        private Looper mLooper;

        Worker(String name) {
            Thread t = new Thread(null, this, name);
            t.start();
            synchronized (mLock) {
                while (mLooper == null) {
                    try {
                        mLock.wait();
                    } catch (InterruptedException ex) {
                    }
                }
            }
        }

        public Looper getLooper() {
            return mLooper;
        }

        public void run() {
            synchronized (mLock) {
                Looper.prepare();
                mLooper = Looper.myLooper();
                mLock.notifyAll();
            }
            Looper.loop();
        }

        public void quit() {
            mLooper.quit();
        }
    }

Мне не совсем понятно, как работает synchronized. Сначала я подумал, что synchronized блокирует объект mLock, но затем, если после t.start() поток конструктора сначала войдет в блок синхронизации, он заблокирует его при mLock.wait() и неявно заблокирует поток «t», заблокировав его вход в синхронизированный блок.

Это явно не так, потому что мой телефон звонит как положено:)

Следующая мысль заключается в том, что синхронизация синхронизирует «кодовый блок» (в этом случае два синхронизированных блока являются независимыми => потоки могут одновременно вводить два разных блока синхронизации без ограничений), и это идеально подходит ...

... пока мой коллега не сказал мне, что mLock.wait() снимает блокировку на mLock и позволяет другому потоку одновременно входить в критическую секцию на mLock.

Я не уверен, что был достаточно ясен, поэтому с удовольствием отвечу на любые дополнительные вопросы по этому вопросу.

Ответы [ 4 ]

8 голосов
/ 17 декабря 2009

Проверьте javadoc на Object.wait () . Это «волшебство» в том, что он сбрасывает монитор, полученный при входе в синхронизированный блок {}. Это позволяет другому потоку получить монитор и вызвать Object.notify () .

Когда другой поток вызывает notify (), чтобы разбудить ожидающий поток от его вызова wait (), ожидающий поток должен повторно получить монитор и заблокировать его до тех пор, пока он не сможет - монитор отбрасывается только на время ожидания () вызов. И уведомляющий поток завершает свой синхронизированный блок до того, как возобновится ожидающий ожидающий поток. Все упорядочено предсказуемо.

1 голос
/ 17 декабря 2009

Да. Если вы прочитаете описание метода wait(), вы поймете, что он заставляет поток снимать блокировку и блокировать, пока другой поток не вызовет notify или notifyAll для блокировки. Текущий поток ожидает, пока он не сможет повторно получить блокировку, и, как только он это сделает, он продолжит выполнение.

Однако приведенный код следует плохой практике, поскольку он «публикует» (то есть делает объект доступным для других потоков) экземпляр Worker до того, как он будет полностью создан. Использование дополнительных барьеров в этом методе в сочетании с природой класса private, вероятно, делает этот случай безопасным, но в целом это не так.

1 голос
/ 17 декабря 2009

synchronized использует объектные мониторы. Вызов wait() для объекта атомарно освобождает монитор объекта (иначе никакой другой поток не сможет взять монитор и выдать notify официанту (ам)).

0 голосов
/ 17 декабря 2009

Позвольте мне объяснить:

Конструктор запускает новый поток, который будет выполнять метод run (). Этот новый поток получит новый объект Looper, сохранит его в поле mLooper и затем запустит цикл сообщений Looper. В промежутке он уведомит () первый поток о том, что mLooper был установлен.

Поэтому первый поток вернется из конструктора только после того, как будет установлен mLooper, что означает, что обработка Looper.loop () 2-м потоком должна начаться в ближайшее время / уже началась.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...