简体   繁体   中英

Non-standard usage of wait notify in concurrent Java programs

I am very familiar with how the wait() / notify() signaling scheme works in Java. However, I realized that the few usage patterns I've seen are variants of the Producer / Consumer scheme, or implementation of a Barrier . Also I have seen implementations of some well-known concurrent problems, such as the Dining Philosophers using wait/notify, but apparently for didactic purposes.

Moreover, all schemes followed the well-behaved recommendation of always invoking wait() inside a loop, and only alter some shared variable after passing the loop, like the following code:

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();
}

My questions is: are there other patterns of usage of wait() / notify() signaling than the ones I cited? Have you ever used it in an non-orthodox way? Why? Here are some more concrete questions to help:

  1. Have you ever seen implementation where a shared variable is altered before exiting the loop? In my example, would there be a reason to assign something in the control points #CP1 and #CP2 ?
  2. Is there some case where you chose to use notify() instead of notifyAll() ? Though the possible performance gain, where you very sure about this wouldn't cause some dead-lock? Why?
  3. Is there some complex scenario, where the waiting condition mycondition depends on more than 1 thread, eg, mycondition= a_ready && b_ready && c_ready ?
  1. sure. one example would be that at #CP1 you could keep a "waiting list". i'm not sure i can think of shared state you might be altering at #CP2 as generally the while loop is only there in the case of "spurious" wakeups (ie you were woken up but really shouldn't have been). also, your handling of InterruptedException is generally a bad idea, as it doesn't allow the thread to be shutdown (a spurious wakeup is different from getting InterruptedException).
  2. If you know that only one waiter will be proceeding, you can use notify instead of notifyAll. this can be much more efficient if there are large number of waiting threads. however , there are some caveats when using notify that you need to be very careful about. a waiter could be notified and interrupted, so your handling of InterruptedException needs to re-notify (so the notification doesn't get lost). this means that even if you only intend a single waiter to be awoken, you need to correctly handle the case that more than one could be awoken. in general, you have to make sure that your code correctly causes another thread to proceed, or you could end up in a deadlock situation.
  3. sure. you could have one flag which indicates that a given thread should proceed and a separate one which indicates that all threads should abort (system shutdown or algorithm abort).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM