Условие против ожидания уведомляет механизм



в чем преимущество использования интерфейса условий/реализаций по сравнению с обычным механизмом уведомления ожидания? Здесь я цитирую комментарии, написанные Дуг Леа:




условные факторы из методов монитора объектов (wait, notify и notifyAll) в отдельные объекты, чтобы дать эффект наличия нескольких наборов ожидания для каждого объекта, объединяя их с использованием произвольных реализаций блокировки. Если блокировка заменяет использование синхронизированных методов и операторов, a Условие заменяет использование методов монитора объектов.




Я вижу, что это более объектно-ориентированный способ реализации механизма ожидания/уведомления. Но есть ли существенное преимущество перед первым?

767   5  

5 ответов:

много преимущества Как упоминалось выше о Интерфейс некоторые важные следующие:

интерфейс входит два дополнительно методы что есть:

1) boolean awaitUntil (дата крайнего срока)бросает InterruptedException: Заставляет текущий поток ожидать, пока он поступает или прерывается, или указанный срок проходит.

2)awaitUninterruptibly() : Заставляет текущий поток ожидать, пока он не сообщается.

Если состояние прерывания текущего потока установлено, когда он входит в этот метод, или он прерывается во время ожидания, он будет продолжать ждать, пока не будет подан сигнал. Когда он, наконец, возвращается из этого метода, его прерванный статус все равно будет установлен.

вышеуказанные два метода отсутствуют в мониторе по умолчанию, который находится в классе объектов, в некоторых ситуации мы хотим установить крайний срок для потока, чтобы ждать, то мы можем сделать это с помощью интерфейса условия.

в некоторых ситуациях мы не хотим прерывать поток и хотим, чтобы текущий поток ждал, пока он не будет сигнализирован, тогда мы можем перейти к методу awaitUninterruptibly, присутствующему в интерфейсе условия.

для получения дополнительной информации состояние интерфейса Java Документация:

http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/Condition.html#awaitUntil%28java.util.Date%29

самая большая проблема заключается в том, что wait/notify подвержен ошибкам для новых разработчиков. Основная проблема заключается в том, что не зная, как правильно обращаться с ними, может привести к неясной ошибке.

  • Если вы звоните уведомить (), прежде чем ждать() он потерян.
  • иногда может быть неясно, вызываются ли notify() и wait() для одного и того же объекта.
  • нет ничего в ожидании / уведомлении, которое требует изменения состояния, но это требуется в большинстве случаев.
  • wait () может вернуться ложно

условие обертывает эту функциональность в выделенный компонент, однако он ведет себя примерно так же.

есть вопрос относительно wait / nofity, опубликованного за несколько минут до этого, и многие, многие другие Search [java]+wait + notify

при использовании Condition: await()/signal() вы можете различить, какой объект или группа объектов/потоков получают определенный сигнал. Вот короткий пример, где некоторые потоки, производители, получат isEmpty сигнал в то время как потребители получат isFull сигнала:

private volatile boolean usedData = true;//mutex for data
private final Lock lock = new ReentrantLock();
private final Condition isEmpty = lock.newCondition();
private final Condition isFull = lock.newCondition();

public void setData(int data) throws InterruptedException {
    lock.lock();
    try {
        while(!usedData) {//wait for data to be used
            isEmpty.await();
        }
        this.data = data;
        isFull.signal();//broadcast that the data is now full.
        usedData = false;//tell others I created new data.          
    }finally {
        lock.unlock();//interrupt or not, release lock
    }       
}

public void getData() throws InterruptedException{
    lock.lock();
    try {
        while(usedData) {//usedData is lingo for empty
            isFull.await();
        }
        isEmpty.signal();//tell the producers to produce some more.
        usedData = true;//tell others I have used the data.
    }finally {//interrupted or not, always release lock
        lock.unlock();
    }       
}

@AfterWorkGuinness

разве вы не должны устанавливать usedData=true/false перед сигнализацией

после код сигнала идти до конца блокировки блока и отпустите его, так что порядок не имеет значения

чтобы конкретно решить, почему наличие нескольких waitsets является преимуществом:

с подождать/уведомить, если есть разные вещи, что потоки ждут (типичным примером является фиксированный размер блокирование очереди, с несколько ниток складывать вещи в очереди и блокировки, когда очередь полна, и другие темы, принимая из очереди и блокировки, когда очередь пуста), то если вы используете сообщим, вызывает планировщик, чтобы забрать кого-нить из ожидать набора для уведомления, вы можете иметь угловые случаи, когда выбранный поток не заинтересован в получении уведомления для конкретной ситуации. Например, очередь будет уведомлять о добавлении чего-то в очередь, но если выбранный поток является производителем, и очередь заполнена, то он не может действовать на это уведомление, которое вы предпочли бы перейти к потребителю. С встроенной блокировкой вы должны использовать notifyAll, чтобы убедиться, что уведомления не теряются.

но notifyAll несет отток с каждым вызовом, где каждый поток просыпается и борется за замок, но только один может добиться прогресса. Другие потоки все бьются вокруг борьбы за замок, пока, по одному за раз, они не могут получить замок и, скорее всего, вернуться к ожиданию. Это порождает много разногласий для не большой пользы, было бы предпочтительнее иметь возможность использовать notify и знать, что уведомлен только один поток, где уведомление имеет отношение к этому потоку.

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

The API doc для Condition имеет пример кода, который показывает использование нескольких условий для ограниченного буфера, он говорит:

мы хотели бы продолжать ждать put threads и принимать потоки в отдельных наборах ожидания, чтобы мы могли использовать оптимизацию только уведомления одного потока за раз когда элементы или пробелы становятся доступными в буфере.

Comments

    Ничего не найдено.