Reentrant Monitor in Java
ReetrantLock is a class that implements Lock Interface. It provides the feature with great flexibility which is why it is the most used lock class in Java. It is necessary for the reliable and . Here, threads are small sub-processes of a big operation. In this article, we are going to learn ReetrantLock and how they manage threads so that they can work efficiently.
Working of ReetrantLock
When try to access a shared resource then, ReetrantLock restricts access to a single thread at a time through lock() and unlock() methods. Suppose there are three people trying to book a train ticket. At the same time, all three people will try to access the booking system, it may happen that two people end up booking the same seat. Reetrant Lock can handle this situation.
First, all three people will request to acquire the booking system through tryLock() method. When one acquires the booking system then, it restricts the particular seat booking through lock() method. After booking, the person will call the unlock() method to release the acquired lock. Till the resources are busy other people will wait in a queue for their turn and after the release of lock they will come in a runnable state.
ReetrantLock tries to provide locks in a fair manner. We can set for how long a thread can acquire lock and also, it ensures that a thread with the longest wait time may get access to lock first. By default the locks are unfair, to make it fair we need to pass Boolean value true in its constructor.
Syntax
ReentrantLock nameOflock = new ReentrantLock(); // by default false Or, ReentrantLock nameOflock = new ReentrantLock(true); // we can make it true
The locks are explicit and can lock or unlock in any order. A single thread can ask for the lock multiple times that”s the reason the name of lock is Reentrant. We can count the number of times a lock is acquired by using getHoldCount() method.
Multithreading Without Reentrant Lock
The following example illustrates the multithreading witout use of Reetrant Lock in above code. We”ve created a class Thrd with a method operation() to perform a given task. Now we”ve created three thread classes and call the operation() method. In the main() method, three objects of thread class are defined and their to start the execution of threads.
Example of Multithreading Without Reentrant Lock
package com.tutorialspoint; class Thrd { static void operation(int data) { for(int i = 1; i <= 4; i++) { System.out.println(data++); } } } class Thrd1 extends Thread { // thread number 1 public void run() { Thrd.operation(1); // method calling } } class Thrd2 extends Thread { // thread number 2 public void run() { Thrd.operation(5); // method calling } } class Thrd3 extends Thread { // thread number 3 public void run() { Thrd.operation(10); // method calling } } public class TestThread { public static void main(String args[]) { // creating object for thread class Thrd1 oprt1 = new Thrd1(); Thrd2 oprt2 = new Thrd2(); Thrd3 oprt3 = new Thrd3(); // Starting the thread operation oprt1.start(); oprt2.start(); oprt3.start(); } }
This produces a different result every time you run this program −
Output
1 2 3 4 10 11 12 13 5 6 7 8
Multithreading With Reentrant Lock
The following example illustrates the use of Reetrant Lock in above code. We”ve created a class Thrd and inside this thread, we”ve defined an object of ReentrantLock. A method operation() store the Boolean value of tryLock() method to a variable named lockAcquired which will check if lock gets acquired by any thread or not. If the lock is acquired lock is given to that thread using lock() method and then the thread start performing the given task. The task will be performed in the try block and the lock will be released in the finally block using unlock() method. Now we”ve created three thread classes and call the operation() method. In the main() method, three objects of thread class are defined and their start() method to start the execution of threads.
Example of Multithreading With Reentrant Lock
package com.tutorialspoint; import java.util.concurrent.locks.ReentrantLock; class Thrd { // creating object of ReentrantLock class private static ReentrantLock lockr = new ReentrantLock(); static void operation(int data) { // give access to lock boolean lockAcquired = lockr.tryLock(); if (lockAcquired) { try { lockr.lock(); // giving lock to thread for(int i = 1; i <= 4; i++) { System.out.println(data++); } // checking lock count System.out.println("Count of Lock: " + lockr.getHoldCount()); } finally { lockr.unlock(); // unlocking the lock } } else { System.out.println("I am in else block"); } } } class Thrd1 extends Thread { // thread number 1 public void run() { Thrd.operation(1); // method calling } } class Thrd2 extends Thread { // thread number 2 public void run() { Thrd.operation(5); // method calling } } class Thrd3 extends Thread { // thread number 3 public void run() { Thrd.operation(10); // method calling } } public class TestThread { public static void main(String args[]) { // creating object for thread class Thrd1 oprt1 = new Thrd1(); Thrd2 oprt2 = new Thrd2(); Thrd3 oprt3 = new Thrd3(); // Starting the thread operation oprt1.start(); oprt2.start(); oprt3.start(); } }
This produces a different result every time you run this program −
Output
I am in else block 5 6 7 8 Count of Lock: 2 I am in else block
Multithreading With Reentrant Lock as True
The following example illustrates the use of Reetrant Lock in above code. We”ve created a class Thrd and inside this thread, we”ve defined an object of ReentrantLock with fair value as true. A method operation() store the Boolean value of tryLock() method to a variable named lockAcquired which will check if lock gets acquired by any thread or not. If the lock is acquired lock is given to that thread using lock() method and then the thread start performing the given task. The task will be performed in the try block and the lock will be released in the finally block using unlock() method. Now we”ve created three thread classes and call the operation() method. In the main() method, three objects of thread class are defined and their start() method to start the execution of threads.
Example of Multithreading With Reentrant Lock as True
package com.tutorialspoint; import java.util.concurrent.locks.ReentrantLock; class Thrd { // creating object of ReentrantLock class private static ReentrantLock lockr = new ReentrantLock(true); static void operation(int data) { // give access to lock boolean lockAcquired = lockr.tryLock(); if (lockAcquired) { try { lockr.lock(); // giving lock to thread for(int i = 1; i <= 4; i++) { System.out.println(data++); } // checking lock count System.out.println("Count of Lock: " + lockr.getHoldCount()); } finally { lockr.unlock(); // unlocking the lock } } else { System.out.println("I am in else block"); } } } class Thrd1 extends Thread { // thread number 1 public void run() { Thrd.operation(1); // method calling } } class Thrd2 extends Thread { // thread number 2 public void run() { Thrd.operation(5); // method calling } } class Thrd3 extends Thread { // thread number 3 public void run() { Thrd.operation(10); // method calling } } public class TestThread { public static void main(String args[]) { // creating object for thread class Thrd1 oprt1 = new Thrd1(); Thrd2 oprt2 = new Thrd2(); Thrd3 oprt3 = new Thrd3(); // Starting the thread operation oprt1.start(); oprt2.start(); oprt3.start(); } }
This produces a different result every time you run this program −
Output
I am in else block I am in else block 5 6 7 8 Count of Lock: 2