This is in continuance with my previous article on Threading in Java: Object Locks - IV. Can a thread acquire multiple locks at the same time ? is the question we will answer in today's article.
Introduction
Can a thread acquire multiple locks at the same time ? . And the answer to this question is Yes! A thread in Java can handle multiple locks. Take the following program.
locks.java
-----------
class processor implements Runnable{
Object objLock;
String name;
public processor(String name, Object objLock){
this.objLock = objLock;
this.name = name;
}
public void run() {
display();
}
public void display() {
synchronized(this){
synchronized(objLock) {
for (int i = 0 ; i<= 5; i++) {
System.out.println("i = " + i + " In thread" + Thread.currentThread() + "acquired lock on this i.e. " + name + " and objLock");
}
}
}
}
}
class locks {
public static void main(String[] args) {
Object objLock = new Object();
processor p1 = new processor("p1",objLock);
processor p2 = new processor("p2",objLock);
Thread t1 = new Thread(p1, "t1");
Thread t2 = new Thread(p1, "t2");
Thread t3 = new Thread(p2, "t3");
Thread t4 = new Thread(p2, "t4");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
Output:
-------
i = 0 In threadThread[t1,5,main]acquired lock on this i.e. p1 and objLock
i = 1 In threadThread[t1,5,main]acquired lock on this i.e. p1 and objLock
i = 2 In threadThread[t1,5,main]acquired lock on this i.e. p1 and objLock
i = 3 In threadThread[t1,5,main]acquired lock on this i.e. p1 and objLock
i = 4 In threadThread[t1,5,main]acquired lock on this i.e. p1 and objLock
i = 5 In threadThread[t1,5,main]acquired lock on this i.e. p1 and objLock
i = 0 In threadThread[t3,5,main]acquired lock on this i.e. p2 and objLock
i = 1 In threadThread[t3,5,main]acquired lock on this i.e. p2 and objLock
i = 2 In threadThread[t3,5,main]acquired lock on this i.e. p2 and objLock
i = 3 In threadThread[t3,5,main]acquired lock on this i.e. p2 and objLock
i = 4 In threadThread[t3,5,main]acquired lock on this i.e. p2 and objLock
i = 5 In threadThread[t3,5,main]acquired lock on this i.e. p2 and objLock
i = 0 In threadThread[t2,5,main]acquired lock on this i.e. p1 and objLock
i = 1 In threadThread[t2,5,main]acquired lock on this i.e. p1 and objLock
i = 2 In threadThread[t2,5,main]acquired lock on this i.e. p1 and objLock
i = 3 In threadThread[t2,5,main]acquired lock on this i.e. p1 and objLock
i = 4 In threadThread[t2,5,main]acquired lock on this i.e. p1 and objLock
i = 5 In threadThread[t2,5,main]acquired lock on this i.e. p1 and objLock
i = 0 In threadThread[t4,5,main]acquired lock on this i.e. p2 and objLock
i = 1 In threadThread[t4,5,main]acquired lock on this i.e. p2 and objLock
i = 2 In threadThread[t4,5,main]acquired lock on this i.e. p2 and objLock
i = 3 In threadThread[t4,5,main]acquired lock on this i.e. p2 and objLock
i = 4 In threadThread[t4,5,main]acquired lock on this i.e. p2 and objLock
i = 5 In threadThread[t4,5,main]acquired lock on this i.e. p2 and objLock
The above program compiles and runs successfully to give us the desired expected output. If you observe the output carefully, you will realize that each and every thread we created in the program was able to acquire a lock on "this" object i.e p1 or p2 as well as the objLock at the same time depending on the context.
Inside main(), threads t1 and t2 are created out of processor object p1 to which the name p1 and the objLock created out of Object class is passed to its constructor. Next, threads t3 and t4 are created out of processor object p2 to which the name p2 and the objLock created out of Object class is passed to its constructor. Thus objLock can be seen by all the Threads. The Thread representing function within run() which is the display() function has the for loop synchronized within "this" and "objLock". Thus any thread has to aquire a lock on itself as well as the lock objLock which is seen by every thread.
When all the threads are started, t1 and t2 race for acquiring a lock on p1 while t3 and t4 race for acquiring a lock on p2 since they are created from p1 and p2 respectively. Lets say t1 acquires a lock on p1 and t3 acquires a lock on p2, then both t1 and t3 compete for objLock. Lets say t1 acquires a lock on objLock and wins the race. Now, t1 will execute the for loop while it is owning both the locks at the same time. Once done, t1 will release both te locks and t3 gets a chance to execute the for loop. Now a similar race condition happens between t2 and t4 and we get a clear in order output.
Points of Interest
Hope this example make it clear that a thread can acquire and own multiple locks. Is it a good practice or not ? we will discuss it later.
History
Initial Revision : 18th June 2021