简体   繁体   English

Java对象锁定和监视器创建如何在JVM内部发生

[英]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. 我的问题不是关于此代码中的错误,也不在于它如何在Java立场上执行。 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. 我仅将其作为参考代码,以便回答的人有一个特定的场景可供参考。我想知道JVM如何在内部创建与此实例相关联的监视对象,以及如何使用OpenJDK实现根据该场景在内部进行对象锁定。 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? 这个stackoverflow问题Java锁概念在内部如何工作? . 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". JLS 17.1提供了有关监视器如何在较高级别上工作的语言说明,但没有“内部发生”的内容。

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. Java中的每个对象都与一个监视器关联,线程可以锁定或解锁监视器。 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; 线程t可以多次锁定特定的监视器。 each unlock reverses the effect of one lock operation. 每次解锁都会逆转一次锁定操作的效果。

In the Java virtual machine, every object and class is logically associated with a monitor. 在Java虚拟机中,每个对象和类在逻辑上都与监视器关联。 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. 为了实现监视器的互斥功能,Java虚拟机将锁(有时称为互斥锁)与每个对象和类关联。 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.) (“锁定对象”是获取与该对象关联的监视器。)

I know in instruction set level how monitorenter and monitorexit opcodes are used to manage synchronized statements. 我知道在指令集级别如何使用monitorentermonitorexit操作码来管理同步语句。 But I am trying to get a deeper understanding trough JVM source code level. 但是我试图通过JVM源代码级别更深入地了解。 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. 但是,由于我在源代码中有很多不足之处,因此我仍在努力将OpenJDK源代码与通过上述链接找到的高级解释进行映射。

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? 因此,熟悉OpenJDK源代码的任何人都可以使用OpenJDK源代码对以下与上述代码段相关的问题进行解释吗? I think ObjectMonitor , BasicLock , Synchronizer classes are more relevant to this explanation. 我认为ObjectMonitorBasicLockSynchronizer类与该解释更为相关。

  1. For which object instance a monitor object is created? 为哪个对象实例创建监视对象? Is it for MyWorker object instance or Object lock1 or both? 它适用于MyWorker对象实例或Object lock1还是两者都适用? Because JSL and Bill Vennams explanations depicts that each object is associated with a monitor. 因为JSL和Bill Vennams的解释描绘了每个对象都与一个监视器相关联。
  2. If it's for MyWorker object instance how monitor is created for the MyWorker object instance? 如果它是MyWorker对象实例如何监控是为创建MyWorker对象实例?
  3. How lock object is created for the reference object Object lock1 we pass 我们如何为参考对象Object lock1创建锁对象
  4. How actually monitor is locked by the lock object for a Thread? 监视器的锁定对象实际上如何锁定线程?

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: 每个 Java对象也是一个监视对象 ,包括反射对象,因此您的代码至少具有以下内容:

  • Class object for MyWorker MyWorker类对象
  • Class object for Random Random类对象
  • Class object for Object Class对象Object
  • Class object for List List类对象
  • Class object for Integer Integer类对象
  • Class object for ArrayList ArrayList类对象
  • ... and many more ... ... 还有很多 ...
  • Random instance assigned to field random 分配给字段random Random实例
  • Object instance assigned to field lock1 分配给字段lock1 Object实例
  • Object instance assigned to field lock2 分配给字段lock2 Object实例
  • ArrayList instance assigned to field list1 分配给字段list1 ArrayList实例
  • ArrayList instance assigned to field list2 分配给字段list2 ArrayList实例
  • Thread instance assigned to local variable t1 Thread实例分配给局部变量t1
  • Thread instance assigned to local variable t2 Thread实例分配给局部变量t2
  • Every Integer instance created by auto-boxing when calling add(random.nextInt(100)) 调用add(random.nextInt(100))时通过自动装箱创建的每个Integer实例

Is it for MyWorker object instance or Object lock1 or both? 它适用于MyWorker对象实例或对象lock1还是两者都适用?

Both

If it's for MyWorker object instance how monitor is created for the MyWorker object instance? 如果用于MyWorker对象实例,如何为MyWorker对象实例创建监视器?
How lock object is created for the reference object Object lock1 we pass 我们如何为参考对象Object lock1创建锁对象
How actually monitor is locked by the lock object for a Thread? 监视器的锁定对象实际上如何锁定线程?

Depends on JVM internals. 取决于JVM内部。 There is no single answer to this, and a "thorough explanation" is beyond the scope of this site. 没有唯一的答案,“彻底的解释”超出了本网站的范围。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM