Using ReentrantLock for thread synchronization

ReentrantLock was introduced in Java 1.5. This can be considered as a replacement for the traditional “wait-notify” method. The basic concept is, every thread need to acquire the lock before entering in to the critical section and should release it after finishing it. And its the most basic concept of synchronization.

ReentrantLock eliminates the use of “synchronized” keyword.

import java.util.concurrent.locks.ReentrantLock;
final ReentrantLock _lock = new ReentrantLock();
private void method() throws InterruptedException
{
   //Trying to enter the critical section
   _lock.lock(); // will wait until this thread gets the lock
   try
   {
      // critical section
   }
   finally
   {
      //releasing the lock so that other threads can get notifies
      _lock.unlock();
   }       

}

Using optional “fairness” parameter with ReentrantLock
ReentrantLock accepts an optional “fairness” parameter in it’s constructor. Normally what happens is, whenever a thread releases the lock anyone of the waiting threads will get the chance to acquire that lock. But there is no predefined order or priority in the selection of the thread (at least from a programmers perspective).

But if we are specifying the fairness parameter as “true” while creating a new ReentrantLock object, it gives us the guaranty that the longest waiting thread will get the lock next. Sounds pretty nice right?

Use of “Condition” in ReentrantLock
Condition can be considered as a separation of monitor methods (wait(), notify() & notifyAll()). For each ReentrantLock we can define a set of conditions and based on that we can make the threads waiting & things like that.

import java.util.concurrent.locks.Condition;
final Condition _aCondition = _lock.newCondition();
private void method1() throws InterruptedException
{
   _lock.lock();
   try
   {
      while (condition 1)
      {
          // Waiting for the condition to be satisfied
          // Note: At this time, the thread will give up the lock
          // until the condition is satisfied. (Signaled by other threads)
          _aCondition.await();
      }
      // method body
   }
   finally
   {
      _lock.unlock();
   }       

}

private void method2() throws InterruptedException
{
   _lock.lock();
   try
   {
      doSomething();
      if (condition 2)
      {
          // Signaling other threads that the condition is satisfied
          // Wakes up any one of the waiting threads
          _aCondition.signal();

          // Wakes up all threads waiting for this condition
          _aCondition.signalAll();
      }       

      // method body
   }
   finally
   {
      _lock.unlock();
   }
}

Update [ Subinkrishna on 19-Feb-2009]
The main difference between RentrantLock and traditional “synchronized” is that, if we are using ReentrantLock, the thread can temporarily release the locks it has when it is going to a wait state. This feature is not available in the traditional way and this can considerably reduce the deadlock situations.

Some useful links

http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/locks/ReentrantLock.html

About these ads