假设我有以下代码片段,其中两个线程访问同一个方法,每个同步语句都使用不同的锁对象。代码如下:
为了实现监视器的互斥能力,Java虚拟机将锁(有时称为互斥量)与每个对象和类关联起来。锁就像一种特权,只有一个线程可以在任何时候“拥有”它。线程不需要获取锁来访问实例或类变量。然而,如果一个线程确实获得了锁,那么其他线程就无法在同一数据上获得锁,直到拥有锁的线程释放它。(“锁定对象”是指获取与该对象关联的监视器。)
因此,是否有熟悉OpenJDK源代码的任何人可以使用OpenJDK源代码为以下与上述代码片段相关的问题提供解释? 我认为 ObjectMonitor,BasicLock,Synchronizer 类与此解释更相关。
1. 为哪个对象实例创建监视器对象?是为
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();
}
}
}
我的问题不是关于这段代码的错误或在java方面如何执行。这段代码工作正常。我只是将其作为参考代码,以便回答者有一个特定的场景可以参考。 我想知道JVM如何在内部创建与此实例关联的监视器对象,并根据该场景使用OpenJDK实现进行对象锁定的内部情况。 我期望得到低级别的解释。
我研究了这个主题几天,但找不到深入的解释。这是我经历过的一些发现:
- 这个stackoverflow问题 Java lock concept how internally works?。但我没有在答案中找到彻底的解释。
- JLS 17.1提供了一个有关监视器如何在高层次上工作的语言解释,但没有提到"内部发生了什么"。
其中最基本的方法是同步,使用监视器实现。Java中的每个对象都与一个监视器相关联,线程可以锁定或解锁该监视器。在任何时刻只有一个线程可以持有监视器上的锁。任何试图锁定该监视器的其他线程都会被阻塞,直到它们可以获得该监视器的锁。线程t可以多次锁定特定的监视器;每个解锁操作都会撤销一个锁定操作的影响。
- 参见Bill Venners的《Java虚拟机内部》第20章“线程同步”(英文)
为了实现监视器的互斥能力,Java虚拟机将锁(有时称为互斥量)与每个对象和类关联起来。锁就像一种特权,只有一个线程可以在任何时候“拥有”它。线程不需要获取锁来访问实例或类变量。然而,如果一个线程确实获得了锁,那么其他线程就无法在同一数据上获得锁,直到拥有锁的线程释放它。(“锁定对象”是指获取与该对象关联的监视器。)
- OpenJDK VM 源代码
因此,是否有熟悉OpenJDK源代码的任何人可以使用OpenJDK源代码为以下与上述代码片段相关的问题提供解释? 我认为 ObjectMonitor,BasicLock,Synchronizer 类与此解释更相关。
1. 为哪个对象实例创建监视器对象?是为
MyWorker
对象实例、Object lock1
还是两者都有?因为JSL和Bill Vennam的说明都描绘了每个对象与监视器相关联。
2. 如果是为MyWorker
对象实例创建的,那么如何为MyWorker
对象实例创建监视器?
3. 如何为引用对象Object lock1
创建锁定对象?
4. 线程如何通过锁定对象实际锁定监视器?