ReentrantLock in Java


Java ReentrantLockViews 1787

This tutorial will help you understand about ReentrantLock class in Java, its method, and implementation using different examples.

ReentrantLock in Java

ReentrantLock in Java

ReentrantLock class in Java implements the Lock interface. This is part of the java.util.cocurrent package that implements synchronization along with fairness. This means it provides locks for the threads in the order in which it is present in the waiting list. We can achieve this by passing the fairness argument while creating a ReentrantLock. As the name suggests, a ReentrantLock allows the thread to re-enter the same acquired lock multiple times as long as it holds the lock. Once done, it can release the lock and thereby allowing threads to acquire it.

You might also like Lock Interface in Java

You might be interested in Deadlock in Java

//Empty constructor
ReentrantLock rl = new ReentrantLock(); 

//Constructor with fairness parameter
ReentrantLock rl = new ReentrantLock(boolean fairness);

Below is the skeleton code of how to implement a ReentrantLock in Java. It is always a best practice to wrap the unlock() method within the finally block. In this way, we can always release the lock even if an unexpected exception arises in the try block.

ReentrantLock rl = new ReentrantLock();
  
  void method_name() {
    rl.lock();
    try {
      //shared resource code
    }
    catch(Exception e) {
      //handle exception
    }
    finally {
      rl.unlock();
    }
  }

Methods of ReentrantLock

Below are the methods present in the ReentrantLock class in Java.

MethodDescription
int getHoldCount()Returns the number of holds on the lock by the current thread
int getQueueLength()Returns the number of threads waiting to acquire the lock
int getWaitQueueLength(Condition condition)Returns the number of threads based on the given condition to acquire the lock
boolean hasQueuedThread(Thread thread)Returns true if the given thread is queued waiting for the lock
boolean hasQueuedThreads()Returns true if there are threads waiting to acquire the lock
boolean hasWaiters(Condition condition)Returns true if there are there are threads waiting to acquire the lock based on the given condition
boolean isFair()Returns true if the fair parameter is set true
boolean isHeldByCurrentThread()Returns true if the lock is held by current thread
boolean isLocked()Returns true if the lock is held by any thread
void lock()Acquires the lock
void lockInterruptibly()Acquires the lock unless the thread is interrupted
Condition newCondition()Returns Condition instance that is used with this lock
boolean tryLock()Acquires the lock if it is no held by other threads
boolean tryLock(long timeperiod, TimeUnit unit)Acquires the lock if not held by other threads by waiting for the specific time
void unlock()Releases the lock

ReentrantLock Example

The below example illustrates the usage of most of the methods present in the ReentrantLock class. We create 3 different threads to execute the same task.

Inside the run() method, we first check if the lock is free to acquire using the tryLock() method. Then we acquire the lock using the lock() method. We can check if the current thread has acquired the lock using the isLocked() method. To get the lock hold count, we can use the getHoldCount() method, and to retrieve the queue length, use the getQueueLength() method. Finally, we release the lock using the unlock() method.

import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockDemo {

  public static void main(String[] args) {
    ReentrantLock rl = new ReentrantLock();
    
    Thread t[] = new Thread[3];
    for(int i=1;i<3;i++) {
      t[i] = new Thread(new Task(rl, "Thread " + i));
    }
    
    for(int i=1;i<3;i++) {
      t[i].start();
    }
    
  }

}

class Task implements Runnable {
  
  String name;
  ReentrantLock rl;
  
  public Task(ReentrantLock rl, String name) {
    this.rl = rl;
    this.name = name;
  }

  public void run() {
    boolean bFlag = false;
    while(!bFlag) {
      boolean bLock = rl.tryLock();
      if(bLock) {
        try {
          System.out.println(name + " going to acquire the lock at: " + new Date());
          Thread.sleep(1000);
          
          rl.lock();
          try {
            System.out.println(name + " acquired the lock at: " + new Date());
            Thread.sleep(1000);
            System.out.println("Acquired lock: " + rl.isLocked());
          }
          catch(InterruptedException e) {
            e.printStackTrace();
          }
          finally {
            System.out.println(name + " releasing the lock");
            rl.unlock();
          }
          
          System.out.println("Lock hold count: " + rl.getHoldCount());
          System.out.println("Queue length: " + rl.getQueueLength());
          System.out.println("Acquired lock: " + rl.isLocked());
          System.out.println("Completed execution of " + name);
          bFlag = true;
          
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        finally {
          System.out.println(name + " releasing the lock");
          rl.unlock();
          System.out.println("Lock hold count: " + rl.getHoldCount());
        }
      }
      else {
        System.out.println(name + " is waiting for the lock");
        try {
          Thread.sleep(1000);
        }
        catch(InterruptedException e) {
          e.printStackTrace();
        }
      }
    }
    
  }
  
}
Thread 1 is waiting for the lock
Thread 2 going to acquire the lock at: Tue Apr 20 15:59:04 IST 2021
Thread 1 is waiting for the lock
Thread 2 acquired the lock at: Tue Apr 20 15:59:05 IST 2021
Thread 1 is waiting for the lock
Acquired lock: true
Thread 2 releasing the lock
Lock hold count: 1
Queue length: 0
Acquired lock: true
Completed execution of Thread 2
Thread 2 releasing the lock
Lock hold count: 0
Thread 1 going to acquire the lock at: Tue Apr 20 15:59:07 IST 2021
Thread 1 acquired the lock at: Tue Apr 20 15:59:08 IST 2021
Acquired lock: true
Thread 1 releasing the lock
Lock hold count: 1
Queue length: 0
Acquired lock: true
Completed execution of Thread 1
Thread 1 releasing the lock
Lock hold count: 0

You might be interested in Multithreading Tutorial

Reference

Translate ยป