Suppose I have following code snippet with two threads accessing same method with two critical sections (synchronized statements). Each of these synchronized statements is given a different lock object. Code as follows :
public class MyWorker {
private Random random = new Random();
private Object lock1 = new Object();
private Object lock2 = new Object();
private List<Integer> list1 = new ArrayList<>();
private List<Integer> list2 = new ArrayList<>();
private void stageOne() {
synchronized (lock1) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
list1.add(random.nextInt(100));
}
}
private void stageTwo() {
synchronized (lock2) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
list2.add(random.nextInt(100));
}
}
private void process() {
for (int i=0; i<1000; i++) {
stageOne();
stageTwo();
}
}
void main() {
Thread t1 = new Thread(this::process);
Thread t2 = new Thread(this::process);
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
My question is not about an error in this code or how this executes in java stand point. This code works fine. I'm only taking this as a reference code so that the person who answers have a particular scenario to refer I want to know how JVM internally create monitor objects associated with this instance and how object locking happens internally according to this scenario using OpenJDK implementation. I am expecting a low level explanation.
I researched on this topic for couple of days and couldn't find an in depth explanation. These are some of my findings I went through :
- This stackoverflow question Java lock concept how internally works?. But I couldn't find a thorough explanation within the answers.
- JLS 17.1 provides an language explanation on how monitor works in high level, but not what "happens internally".
The most basic of these methods is synchronization, which is implemented using monitors. Each object in Java is associated with a monitor, which a thread can lock or unlock. Only one thread at a time may hold a lock on a monitor. Any other threads attempting to lock that monitor are blocked until they can obtain a lock on that monitor. A thread t may lock a particular monitor multiple times; each unlock reverses the effect of one lock operation.
- And Bill Venners's Inside Java Virtual Machine Chapter 20 "Thread Synchronization"
In the Java virtual machine, every object and class is logically associated with a monitor. For objects, the associated monitor protects the object's instance variables. For classes, the monitor protects the class's class variables. If an object has no instance variables, or a class has no class variables, the associated monitor protects no data.
To implement the mutual exclusion capability of monitors, the Java virtual machine associates a lock (sometimes called a mutex) with each object and class. A lock is like a privilege that only one thread can "own" at any one time. Threads need not obtain a lock to access instance or class variables. If a thread does obtain a lock, however, no other thread can obtain a lock on the same data until the thread that owns the lock releases it. (To "lock an object" is to acquire the monitor associated with that object.)
- OpenJDK VM source code
I know in instruction set level how monitorenter and monitorexit opcodes are used to manage synchronized statements. But I am trying to get a deeper understanding trough JVM source code level. But yet I'm struggling to map the OpenJDK source code with the high level explanations I found via above links since there is lot going under the hood in source code.
So can anyone who is familiar with OpenJDK source code give an explanation for following questions related to above code snippet using OpenJDK source code? I think ObjectMonitor, BasicLock, Synchronizer classes are more relevant to this explanation.
- For which object instance a monitor object is created? Is it for
MyWorker
object instance orObject lock1
or both? Because JSL and Bill Vennams explanations depicts that each object is associated with a monitor. - If it's for
MyWorker
object instance how monitor is created for theMyWorker
object instance? - How lock object is created for the reference object
Object lock1
we pass - How actually monitor is locked by the lock object for a Thread?