The knowledge sharing zone - Guruzon.com

What is Reentrant lock in java

This tutorial contains the details about - What is Reentrant lock, Limitations of synchronized, Advantages and disadvantages of reentrantlock, Choosing between synchronized and Reentrantlock, Implicit locking vs Explicit locking.
reviews

ReentrantLock in java

  • Till Java 1.4, We can coordinating the access to shared data using "synchronize" and "volatile" keywords.
  • Then Java 5.0 adds another option: ReentrantLock.
  • Remember that "ReentrantLock is not a replacement for implicit locking (eg. using synchronized), but rather an alternative with advanced features for when you found implicit locking is limited.
  • Before going deep into ReentrantLock, First understand the concept of Implicit locking & Explicit locking.

What is Implicit locking in java

  • In java, We can use "synchronized" keyword for implicit locking.
  • Internally, synchronized keyword enforces that "only one thread executes in a critical section at a time".
  • In implicit locking mechanism, JVM takes care of locking (using lock/monitor of the shared object/resource) when you enter the synchronized block/method. And JVM automatically  does the unlocking (by releases the lock/monitor of the shared object/resource) at the end of the synchronized block/method.
  • You can think of using "synchronized" for locking implicitly, And using "java.util.concurrent.locks.Lock" objects for locking explicitly.
  • When you use synchronized keyword (implicit locking), You don't have to remember to release the lock in a finally block since, at the end of the synchronized block (or method), code for releasing the lock will be generated to automatically.

Limitations of implicit locking

  • Implicit locking has some functional limitations like : "It's not possible to attempt to acquire a lock without being willing to wait for it forever", This limitation leads to deadlock quite often in most of the situations.
  • In other words, We can say that It's impossible to implement non-blocking kind of locking mechanism with implicit-locking.
  • With implicit locks, You can't cancel a lock acquisition once it is started hence you can't implement time-budgeted activities with it (eg. try to obtain lock within 5 seconds else come back, don't wait for lock forever!!).

What is Explicit locking

  • From Java 5.0 onwards, The java.util.concurrent.locks package provides explicit locking facility.
  • The basic aim of explicit locking is same as implicit locking "Ensure that only one thread accesses a shared resource at a time, Moreover it also support the wait/notify mechanism using Condition objects".
  • Explicit locking (using java.util.concurrent.locks.Lock) provides unconditional, polled, timed & interruptible lock acquisition, Moreover all the lock and unlock operations are explicit.
  • This way Explicit locking allow you to get more flexibility to implement complex critical section.
  • Remember, When you use explicit locking (eg. using ReentrantLock), You are required to release the lock manually after the critical section (best place to release the lock is from finally block).

Use of ReentrantLock in java

  • ReentrantLock is concrete class of java.util.concurrent.locks.Lock interface, provides advanced explicit locking mechanism in java.
  • ReentrantLock allows threads to re-request locks they already own, This means it allows them to reenter their mutually exclusive sections.
  • ReentrantLock provides timed or polled lock acquisition ( using tryLock() API), That means :
    • "Try to acquire the lock if lock is free, Else don't block / wait for it" (ex. boolean tryLock() API call ).
    • Moreover it provides timed-wait facility also that means : "Try to acquire the lock if lock is free, Else wait for given maximum-time & don't get blocked foreever." (ex. boolean tryLock(long timeout, TimeUnit unit) API call ).
  • You can also apply reentrant lock across multiple methods also (eg. acquire lock from methodA() methodA() calls methodB() then release the lock from methodB()), This is only possible with reentrantlock, And it's not possible with synchronized (implicit locking).
  • Best use of ReentrantLock lock is when you need to acquire multiple locks for some operation.
    • For example, When you want to acquire multiple-locks for some critical operation, It may be possible that you acquire lock on first object & now waiting for the second object lock, This causes the performance penalty.
    • But with ReentrantLock, If you don't acquire all the locks at once, You can release the locks which you acquired & then "Try again to acquire them again at once", This way it gives better performance & non-blocking execution.
    • You can use tryLock() method "To attempt to acquire multiple locks on different objects, And retry if multiple locks are not acquired".
    • Banking application - transfer money usecase : 
      • Try to acquire lock on both the objects, If both the lock acquired, call transferMoney().
      • Else If both the locks cannot be acquired within the specified time, returns a failure status so that the operation can fail gracefully or Retry after some interval.

Choosing between Synchronized (implicit locking) vs ReentrantLock (explicit locking)

  • ReentrantLock provides advanced mechanism for situations where intrinsic / implicit locking is not practical.
  • You can use ReentrantLock if you need its advanced features like : Timed, Polled or Interruptible lock acquisition, fair queuing or non-blocking locking. Otherwise prefer synchronized.

Advantages of ReentrantLock in java

  • It provides facility to attempt to acquire a lock without being willing to wait for it forever. In other words, It provides non-blocking locking structure using tryLock() API.
  • It's Easy to implement time-budgeted activities using tryLock(timeout) & unlock() APIs of ReentrantLock class.
  • ReentrantLock class defines methods like isLocked() and getLockQueueLength()  and some associated protected access methods that may be useful for instrumentation and monitoring.
  • ReentrantLock class also implements optional "fairness policy" which favors the granting the access to the longest-waiting thread & avoids starvation. But remember that overall throughput will reduce if you enable fairness policy.

Disadvantages of ReentrantLock in java

  • ReentrantLock is more dangerous than synchronized because If you forget to call unlock() in a finally block, You'll hurt innocent threads waiting for that lock.
  • With ReentrantLock, It's difficult to detect & identify deadlock because of thread dumps complexity, But with implicit-lock you can easily debug the threading problems.

ReentrantLock example in java

It is recommended practice to always immediately follow a call to lock with a try block, most typically in a before/after construction such as:

        Lock lock = new ReentrantLock();
        lock.lock();
        try {
            // update object state
            // catch exceptions and restore invariants if necessary
        } finally {
            lock.unlock();
        }

Example 1:

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

// This class simulates a situation where only one ATM machine is available and
// and five people are waiting to access the machine. Since only one person can
// access an ATM machine at a given time, others wait for their turn

public class ATMMachineSimulationWithReentrantLock {

    public static void main(String[] args) {
        // Here the ATM machine is shared resource
        // among multiple persons so we'll
        // represent "atm machine" using "reentrant lock"

        Lock atmMachine = new ReentrantLock();

        // list of people waiting to access the machine
        new Person(atmMachine, "John");
        new Person(atmMachine, "Mike");
        new Person(atmMachine, "Thomas");
        new Person(atmMachine, "Merry");
        new Person(atmMachine, "Natasha");
    }
}

// Each Person is an independent thread,
// their access to the common resource (the ATM machine in this case)
// needs to be synchronized using a lock

class Person extends Thread {
    private Lock atmMachine;

    public Person(Lock machine, String name) {
        this.atmMachine = machine;
        this.setName(name);
        this.start();
    }

    public void run() {
        try {
            System.out.println(getName() + " waiting to access an ATM machine");
            atmMachine.lock();

            // Critical region : start
            System.out.println(getName() + " is accessing an ATM machine");
            // simulate the time required for withdrawing amount
            Thread.sleep(1000);
            // Critical region : end

        } catch (InterruptedException ie) {
            System.err.println(ie);
        } finally {
            atmMachine.unlock();
        }
    }
}
// Output:
// John waiting to access an ATM machine
// Natasha waiting to access an ATM machine
// Merry waiting to access an ATM machine
// Thomas waiting to access an ATM machine
// Mike waiting to access an ATM machine
// John is accessing an ATM machine
// Natasha is accessing an ATM machine
// Merry is accessing an ATM machine
// Thomas is accessing an ATM machine
// Mike is accessing an ATM machine

Example 2 :

<coming-soon>

Interview Questions related to this concept

Answers for the below mentioned questions you can easily find out from the above article.


Is ReentrantLock is replacement of synchronized in java


When to chose implicit locking and explicit locking in java


How to implement explicit locking in java


What is different between implicit and explicit locking in java


What are the limitations of implicit locking or synchronized in java


What are the advantages of explicit locking in java


What are the advantages of ReentrantLock in java


How ReentrantLock works


Do you know any usecase of ReentrantLock or Explicit locking


Is there any feature in ReentrantLock to avoid lock starvation?


Is it okay for a thread to acquire lock on obj again, and such an attempt will succeed?


You would also like to read:

Difference between synchronized and Reentrantlock in java

Comments :


nicely explained

up vote icon down vote icon
Name :
Email :
Comment :
Verify Text :
capch image, refresh page if not loaded somehow