Skip to content
Go back

Reentrant Locks in Java

Table of contents

Open Table of contents

Introduction

Locks are a mechanism to prevent access of a resource to multiple threads at the same time.

Locks vs synchronized keyword

private static ReentrantLock lock = new ReentrantLock();

private static void accessResource() {
  lock.lock();
  try {
    // do work
    // access the resource
  } finally {
    lock.unlock();
  }
}

This is very similar to synchronized keyword

private static void accessResource() {
  synchronized (this) { // same as lock.lock();
    // do work
    // access the resource
  } // same as lock.unlock();
}

Locks are explicit i.e. we have to do most of the things manually while synchronized is implicit as JVM manages the locking logic behind the scenes. We do not have to tell the code exactly when to grab the key or when to give it back.

Synchronized keyword can be used to make a method thread safe as well as make a block of code thread safe. Same can be achieved with reentrant locks too.

Featuresynchronized (Implicit)Lock (Explicit)
Ease of UseVery easyTricky if not used carefully
ReleaseAutomatic (at end of block).Manual (must use finally block).
FlexibilityRigid; block-structured only.High; can span across methods.
InterruptionThread will wait forever.Can be interrupted or time out.

Reentrant locks

Why “Reentrant”? Because we can call lock() method multiple times which is not possible with synchronized.

private static ReentrantLock lock = new ReentrantLock();

private static void accessResource() {
  lock.lock();
  lock.lock();
  // do work
  // access the resource
  lock.unlock();
  lock.unlock();
}
private static ReentrantLock lock = new ReentrantLock();

private static void accessResource() {
  lock.lock();
  // update the shared resource
  if (someCondtion()) {
    accessResource(); // same thread entering the same lock again, increasing the `getHeldCount()`
  }
  lock.unlock();
}

Reentrant lock has a constructor with boolean parameter that decides if it will be fair lock. By default locks are unfair. By fair it means that it allows the thread waiting the longest in wait queue to acquire lock first. Unfair lock will allow threads that are making call to acquire lock while there are other threads waiting in wait queue, unfair but fast.

AdvantageDisadvantage
Fair lockEqual chance for all threadsSlower
Unfair lockFaster (more throughput)Possible thread starvation (threads may wait forever)

Reentrant lock has a utility method tryLock()

private static ReentrantLock lock = new ReentrantLock();

private static void accessResource() {
  boolean lockAquired = lock.tryLock(5, SECONDS);
  if (lockAcquired) {
    try {
      // do work
      // access the resource
    } finally {
      lock.unlock();
    }
  } else {
    // do something else when lock is not available
  }
}

Share this post on:

Next Post
Consumer group in kafka