Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How java object locking and monitor creation happens internally inside JVM

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.

  1. For which object instance a monitor object is created? Is it for MyWorker object instance or Object lock1 or both? Because JSL and Bill Vennams explanations depicts that each object is associated with a monitor.
  2. If it's for MyWorker object instance how monitor is created for the MyWorker object instance?
  3. How lock object is created for the reference object Object lock1 we pass
  4. How actually monitor is locked by the lock object for a Thread?
like image 351
Insightcoder Avatar asked Jun 20 '18 20:06

Insightcoder


People also ask

How is locking mechanism implemented by JVM?

Multiple locksFor each object, the JVM maintains a count of the number of times the object has been locked. An unlocked object has a count of zero. When a thread acquires the lock for the first time, the count is incremented to one. Each time the thread acquires a lock on the same object, a count is incremented.

How does a lock work internally?

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.

How are locks implemented in Java?

Locks are implemented internally using synchronized blocks. Therefore, we can use locks instead of synchronized keywords in Java. A Lock is more flexible and more sophisticated than a synchronized block.

What is object locking in Java?

Object level lock is a mechanism when we want to synchronize a non-static method or non-static code block such that only one thread will be able to execute the code block on a given instance of the class. This can always be done to make instance-level data thread-safe.


1 Answers

For which object instance a monitor object is created?

Every Java object is also a monitor object, including reflection objects, so your code has at least the following:

  • Class object for MyWorker
  • Class object for Random
  • Class object for Object
  • Class object for List
  • Class object for Integer
  • Class object for ArrayList
  • ... and many more ...
  • Random instance assigned to field random
  • Object instance assigned to field lock1
  • Object instance assigned to field lock2
  • ArrayList instance assigned to field list1
  • ArrayList instance assigned to field list2
  • Thread instance assigned to local variable t1
  • Thread instance assigned to local variable t2
  • Every Integer instance created by auto-boxing when calling add(random.nextInt(100))

Is it for MyWorker object instance or Object lock1 or both?

Both

If it's for MyWorker object instance how monitor is created for the MyWorker 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?

Depends on JVM internals. There is no single answer to this, and a "thorough explanation" is beyond the scope of this site.

like image 86
Andreas Avatar answered Sep 22 '22 05:09

Andreas