Ожидание против ожидания в синхронизированных методах (java)

#java #multithreading #if-statement #concurrency #wait

#java #многопоточность #if-оператор #параллелизм #подождите

Вопрос:

Привет, я довольно новичок в Java, и теперь я начинаю изучать параллелизм Java. И у меня есть небольшие сомнения по поводу синхронизированных методов: я видел, что могу получить те же результаты, используя If else внутри синхронизированного метода, каждый раз проверяя, выполнено ли условие для выполнения действия, как при использовании подхода ожидания / уведомления.

Поскольку я получаю тот же результат, мне интересно, имеет ли подход If else какие-либо преимущества или недостатки по сравнению с подходом wait и notify? Я полагаю, что эффективность будет недостатком, поскольку If всегда проверяет условие, Who le wait просто останавливается и ждет уведомления. Но есть ли какие-либо другие преимущества или недостатки?

Спасибо!

Комментарии:

1. Можете ли вы показать код, который вы пытаетесь сравнить?

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

Ответ №1:

Вы смешиваете две концепции. If-Else и Wait-Notify совершенно разные. Вы хотите, чтобы два потока взаимодействовали друг с другом, то есть там, где будет использоваться Wait-Notify, в то время как if-else является общим условным выражением.

Вы не можете заставить два потока взаимодействовать друг с другом, просто используя условие if-else . Вы можете написать свой код, который делает его похожим на то, что он делает, однако вы просто не позволяете потокам взаимодействовать друг с другом.

Более того, это может привести к нежелательным последствиям / вычислительным состояниям. Рано или поздно у вас будет код hotchpotch.

Ответ №2:

синхронизированный блок делает код потокобезопасным. Вы хотели бы использовать wait() и notify() или notifyAll() , если хотите быть более эффективными.

Например, если ваш общий ресурс представляет собой список, несколько потоков совместно используются. Если вы поместите его в синхронизированный блок монитора, потоки будут постоянно подключаться и запускать код во время переключения контекста. Даже если список полный!!

Следовательно wait() , используется на мониторе (объект внутри synchronized(..) ) как механизм, позволяющий «сообщить» всем потокам расслабиться и прекратить использование циклов процессора до дальнейшего уведомления или notifyAll() .

 synchronized(monitor) {

    while( list.isEmpty() ) 
       monitor.wait();
    doSomething(...)
}
  

В приведенном выше примере doSomething() будет выполняться только тогда, когда список не пуст, после выполнения другого потока notify() или notifyAll() где-то еще в коде.

НО со следующим кодом:

 synchronized(monitor) {

    if(!list.isEmpty())
        doSomething(...)
}
  

Когда поток поступает в синхронизированный блок, возможны 3 сценария:

  1. Список пуст: doSomething() не будет выполнен.
  2. Список НЕ пуст: doSomething() может быть выполнен правильно или…
  3. Если сразу после и было переключение контекста if doSomething , а другой поток получил все элементы списка, после другого потока с переключением контекста будет выполняться doSomethig() в пустом списке.

Итак, просто подводя итог, если вы используете wait / notify, вы гарантируете более эффективный код! поток не будет работать, когда в этом нет необходимости.

Комментарии:

1. Если другой поток использует synchronized правильно, сценарий 3 не может произойти, поскольку это точка synchronized блока, гарантирующая, что другие потоки не смогут вмешиваться. С другой стороны, если другой поток не работает synchronized правильно, это также приведет к нарушению кода на основе цикла, поскольку в этом отношении нет принципиальной разницы между an if и a while . В обоих случаях doSomething(…) выполняется isEmpty() проверка и полагается на synchronized предотвращение промежуточных изменений.

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