Ins*_*der 8 java concurrency multithreading jvm-hotspot
假设我有以下代码片段,其中两个线程访问具有两个关键部分(同步语句)的相同方法.这些同步语句中的每一个都被赋予不同的锁定对象.代码如下:
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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
我的问题不是关于这段代码中的错误或者它是如何在java站点中执行的.这段代码工作正常.我只是将其作为参考代码,以便回答的人有一个特定的场景来引用我想知道JVM如何在内部创建与此实例关联的监视器对象以及如何使用OpenJDK实现根据此场景在内部进行对象锁定.我期待一个低级别的解释.
我研究了这个主题几天,但是找不到深入的解释.这些是我经历的一些调查结果:
这些方法中最基本的是同步,它是使用监视器实现的.Java中的每个对象都与一个监视器相关联,一个线程可以锁定或解锁.一次只有一个线程可以锁定监视器.尝试锁定该监视器的任何其他线程都将被阻止,直到它们可以获得该监视器上的锁定为止.线程t可以多次锁定特定监视器; 每次解锁都会逆转一次锁定操作的效果.
在Java虚拟机中,每个对象和类在逻辑上与监视器关联.对于对象,关联的监视器保护对象的实例变量.对于类,监视器保护类的类变量.如果对象没有实例变量,或者类没有类变量,则关联的监视器不保护数据.
为了实现监视器的互斥功能,Java虚拟机将锁(有时称为互斥锁)与每个对象和类相关联.锁就像一个特权,任何时候只有一个线程可以"拥有".线程无需获取锁来访问实例或类变量.但是,如果一个线程确实获得了一个锁,那么在拥有该锁的线程释放它之前,没有其他线程可以获得对相同数据的锁定.("锁定对象"是获取与该对象关联的监视器.)
我在指令集级别知道如何使用monitorenter和monitorexit操作码来管理同步语句.但我试图通过JVM源代码级别更深入地了解.但是我正在努力将OpenJDK源代码映射到我通过上面链接找到的高级解释,因为源代码中有很多内容.
那么熟悉OpenJDK源代码的人是否可以使用OpenJDK源代码解释以下与上述代码片段相关的问题?我认为ObjectMonitor,BasicLock,Synchronizer类与此解释更相关.
MyWorker对象实例Object lock1还是两者兼而有之?因为JSL和Bill Vennams的解释描述了每个对象都与监视器相关联.MyWorker对象实例,那么如何为对象实例创建监视器MyWorker?Object lock1
我们传递的引用对象创建锁定对象为哪个对象实例创建监视器对象?
每个 Java对象也是一个监视器对象,包括反射对象,因此您的代码至少具有以下内容:
MyWorkerRandomObjectListIntegerArrayListRandom 分配给字段的实例 randomObject 分配给字段的实例 lock1Object 分配给字段的实例 lock2ArrayList 分配给字段的实例 list1ArrayList 分配给字段的实例 list2Thread 实例分配给局部变量 t1Thread 实例分配给局部变量 t2Integer调用时由自动装箱创建的每个实例add(random.nextInt(100))它适用于MyWorker对象实例还是Object lock1或两者兼而有之?
都
如果是MyWorker对象实例,那么如何为MyWorker对象实例创建监视器?
如何为引用对象创建锁定对象我们传递的对象lock1
如何实际监视器被线程的锁定对象锁定?
取决于JVM内部.对此没有单一的答案,"彻底的解释"超出了本网站的范围.