Нестандартное использование уведомления об ожидании в параллельных программах Java

1

Я очень хорошо знаком с тем, как схема сигнализации wait()/notify() работает на Java. Однако я понял, что несколько моделей использования, которые я видел, являются вариантами схемы Продюсер/Потребитель или реализация Барьера. Также я видел реализации некоторых известных параллельных проблем, таких как обеденные философы, использующие wait/notify, но, видимо, для дидактических целей.

Более того, все схемы следовали хорошо зарекомендовавшей себя рекомендации всегда вызывать wait() внутри цикла и только изменяют некоторую общую переменную после прохождения цикла, как и следующий код:

synchronized(mon) {

   // #CP1 - Do not change variables here

   while !(mycondition) {
      try{
         // #CP2 Do not change variables here
         mon.wait();
      } catch(catch (InterruptedException e) {  e.printStackTrace(); }
   }

   // Condition satisfied - Now you can change!      
   makeOperation();

   // Tell others that you're done and exit
   mon.notifyAll();
}

Мои вопросы: есть ли другие способы использования сигнализации wait()/notify() чем те, которые я привел? Вы когда-нибудь использовали его неправославным способом? Зачем? Вот еще несколько конкретных вопросов, которые помогут:

  1. Вы когда-нибудь видели реализацию, где общая переменная изменяется перед выходом из цикла? В моем примере возникла бы причина назначить что-то в контрольных точках #CP1 и #CP2?
  2. Есть ли какой - нибудь случай, когда вы решили использовать notify() вместо notifyAll()? Хотя возможное усиление производительности, когда вы очень уверены в этом, не вызовет какой-то мертвой блокировки? Зачем?
  3. Есть ли какой-то сложный сценарий, где условие ожидания mycondition зависит от более чем одного потока, например mycondition= a_ready && b_ready && c_ready?
  • 0
    Я бы сказал, что в наше время использование wait и notify является нестандартным способом управления потоками. Можно утверждать, что с ними ничего нельзя сделать, чего нельзя сделать с помощью инструментов java.util.concurrent и без краевых эффектов.
  • 0
    @OldCurmudgeon: Я согласен, что wait и notify являются стандартными, так как java.util.concurrent . Но есть ли кто-то использующий java.util.concurrent.locks.Condition , который является своего рода высокоуровневой заменой для wait/notify ? Если это так, вопрос все еще остается в силе.
Показать ещё 2 комментария
Теги:
multithreading
wait
design-patterns
notify

1 ответ

1
  1. конечно. одним примером может быть то, что в # CP1 вы можете сохранить "список ожидания". Я не уверен, что могу думать об общем состоянии, которое вы можете изменить на # CP2, поскольку в общем случае цикл while существует только в случае "ложных" пробуждений (т.е. вы проснулись, но на самом деле этого не должно было быть). Кроме того, ваша обработка InterruptedException, как правило, является плохой идеей, так как она не позволяет отключить поток (ложное пробуждение отличается от получения InterruptedException).
  2. Если вы знаете, что будет работать только один официант, вы можете использовать уведомление вместо notifyAll. это может быть намного более эффективным, если имеется большое количество ожидающих потоков. однако есть некоторые предостережения при использовании уведомления о том, что вы должны быть очень осторожны. официант может быть уведомлен и прерван, поэтому ваше обращение с InterruptedException необходимо повторно уведомить (чтобы уведомление не потерялось). это означает, что даже если вы только намерены разбудить одного официанта, вам нужно правильно обработать дело, чтобы можно было разбудить больше одного. в общем, вы должны убедиться, что ваш код правильно вызывает другой поток, или вы можете оказаться в ситуации взаимоблокировки.
  3. конечно. вы можете иметь один флаг, который указывает, что данный поток должен быть продолжен, и отдельный, который указывает, что все потоки должны прерываться (выключение системы или прерывание алгоритма).

Ещё вопросы

Сообщество Overcoder
Наверх
Меню