новый класс против нового объекта для блокировки в Java - PullRequest
0 голосов
/ 26 декабря 2018

Есть ли разница между блокировкой, созданной из класса и из объекта?

class AWTInvocationLock {}
Object lock = new AWTInvocationLock();

public void foo(){
    synchronized (lock) {
        // ...
    }
}

public Object lock = new Object();
public void bar(){
    synchronized (lock) {
        // ...
    }
}

В java.awt Я вижу этот код, и мне интересно узнать об идее class AWTInvocationLock {} вместо просто new Object()

static void invokeAndWait(Object source, Runnable runnable)
    throws InterruptedException, InvocationTargetException
{
    // ...

    class AWTInvocationLock {}
    Object lock = new AWTInvocationLock();

    InvocationEvent event =
        new InvocationEvent(source, runnable, lock, true);

    synchronized (lock) {
        Toolkit.getEventQueue().postEvent(event);
        while (!event.isDispatched()) {
            lock.wait();
        }
    }

    //...
}

Ответы [ 2 ]

0 голосов
/ 26 декабря 2018

Когда вызывается метод, который блокирует конкретный объект, он блокирует этот экземпляр объекта до завершения вызова метода.С этой точки зрения, не имеет значения, где вы создаете экземпляр объекта, который нужно заблокировать на , если он остается тем же объектом во время вызова метода для достижения результатов блокировки .

Ваш первый сегмент кода создает отдельный объект, который определен в экземпляре обработчика (класс, в котором есть метод foo()).Это означает, что этот обработчик будет не однопоточным, потому что он всегда будет блокировать тот же экземпляр созданного вами объекта блокировки.

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

0 голосов
/ 26 декабря 2018

Лучше немного описать код:

class AWTInvocationLock {}
    Object lock = new AWTInvocationLock();

    InvocationEvent event =
        new InvocationEvent(source, runnable, lock, true);

    synchronized (lock) {
        Toolkit.getEventQueue().postEvent(event);
        while (!event.isDispatched()) {
            lock.wait();
        }
    }

Ссылка на объект блокировки выходит за пределы локальной области видимости.Ссылка хранится в объекте InvocationEvent:

InvocationEvent event =
            new InvocationEvent(source, runnable, lock, true);

Поток отправки EventQueue прослушивает опубликованные объекты Event.Поток вызывает метод dispatch() для каждого события.Я не смотрел исходный код, но думаю, что псевдокод метода InvocationEvent.dispatch() выглядит следующим образом:

 1. synchronize(lock)
 2. runnable.run() -- store any exceptions to a "throwable" reference variable
 3. lock.notify()

Таким образом, поток диспетчеризации EventQueue вызывает notify() объекта блокировки, который освобождает поток, вызывающий invokeAndWait() из вызова wait() в следующей строке.

Есть ли разница между блокировкой, созданной из класса и из объекта?

AWTInvocationLock - это именованный внутренний класс с областью действия метода.Я никогда не видел никого в дикой природе.Это действительно неясная часть языка, и та, о которой почти никто из моих знакомых не знает.Я бы никогда не использовал его из-за этого и потому, что Javadoc даже не распознает их и не будет генерировать для них документацию!

...