Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert wait & notifyAll code to use Java 1.5 Lock object

We use code that uses syncronized blocks around segments of code with a lot of wait and notifyAll() calls. We are trying to convert these to use Java 5 Lock.lock() and Lock.unlock() methods. How do I migrate this code to remove all the wait and notifyAll calls. I do not know the equivalent to these using the new Locking features.

Any links with examples would be appreciated.

Thanks in Advance

Eq., the following code needs to be converted to use Lock.lock() and lock.unlock The first part to remove the synchronized block is simple as I just need to call lock() method. The question is what can be done for the notifyAll() and wait methods.

     synchronized( LOCK )
            {
                while( !Thread.interrupted() )
                {
                 try
                    {

                        working = runRules();

                        if( !working )
                            LOCK.notifyAll();

                        LOCK.wait( working ? shortTimeout : longTimeout );
                    }
                    catch( final InterruptedException e )
                    {
                        Package.log.info( "Thread was interrupted.  Exiting.", e );
                        return;
                    }
                }
            }
like image 923
Nadeem Avatar asked May 03 '11 20:05

Nadeem


2 Answers

Use the Conditions provided by the java.util.concurrent.locks package:

 final Object monitor = ...

 ...

 synchronized (monitor) {

     while (!condition) monitor.wait();
     ... do something ...
 }

becomes:

 final ReentrantLock lock = ...;
 final Condition cvar = lock.newCondition();

 ...

 lock.lock();

 try {

     while (!condition) cvar.await();
     ... do something ... 

 } finally {

     lock.unlock();
 }

The signalling side is pretty similar:

 synchronized (monitor) {

      ... do something ...
      monitor.notify();
 }

becomes:

 lock.lock();

 try {

     ... do something ...
     cvar.signalAll();

 } finally {

     lock.unlock();
 }
like image 186
Dirk Avatar answered Oct 31 '22 18:10

Dirk


Use Condition objects provided by the Lock.newCondition() factory method. The waiting and notification aspects of an Object's monitor were factored out into this interface.

From a migration point of view:

  • wait() -> await()
  • wait(long) -> await(long, TimeUnit.Millis) or awaitNanos(long * 10000000)
  • notify() -> signal()
  • notifyAll() -> signalAll()

However, conditions are more powerful than monitors in several ways. Firstly they are more fine grained, so you can have multiple conditions for different things. If I have a bounded blocking collection for instance, I can have a condition for full and a condition for empty, and await and notify these separately as elements are added or removed.

There are also additional await variants that allow you to await without being interrupted and await until a certain specific date (time).

The javadocs of the Condition class are very good and describe it and its use in great detail.

like image 35
Jed Wesley-Smith Avatar answered Oct 31 '22 20:10

Jed Wesley-Smith