[英]How java object locking and monitor creation happens internally inside JVM
假設我有以下代碼片段,其中兩個線程使用兩個關鍵部分(同步語句)訪問同一方法。 這些同步語句中的每一個都被賦予一個不同的鎖對象。 代碼如下:
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實現根據該場景在內部進行對象鎖定。 我期待一個低水平的解釋。
我花了幾天的時間研究這個主題,卻找不到深入的解釋。 這些是我經歷的一些發現:
這些方法中最基本的是同步,它是使用監視器實現的。 Java中的每個對象都與一個監視器關聯,線程可以鎖定或解鎖監視器。 一次只能有一個線程在監視器上保持鎖。 嘗試鎖定該監視器的所有其他線程將被阻止,直到它們可以在該監視器上獲得鎖定為止。 線程t可以多次鎖定特定的監視器。 每次解鎖都會逆轉一次鎖定操作的效果。
在Java虛擬機中,每個對象和類在邏輯上都與監視器關聯。 對於對象,關聯的監視器將保護對象的實例變量。 對於類,監視器將保護類的類變量。 如果對象沒有實例變量,或者一個類沒有類變量,則關聯的監視器將不保護任何數據。
為了實現監視器的互斥功能,Java虛擬機將鎖(有時稱為互斥鎖)與每個對象和類關聯。 鎖就像特權,一次只能有一個線程“擁有”。 線程無需獲取鎖即可訪問實例或類變量。 但是,如果某個線程確實獲得了鎖,則只有擁有該鎖的線程將其釋放后,其他線程才能在同一數據上獲得鎖。 (“鎖定對象”是獲取與該對象關聯的監視器。)
我知道在指令集級別如何使用monitorenter和monitorexit操作碼來管理同步語句。 但是我試圖通過JVM源代碼級別更深入地了解。 但是,由於我在源代碼中有很多不足之處,因此我仍在努力將OpenJDK源代碼與通過上述鏈接找到的高級解釋進行映射。
因此,熟悉OpenJDK源代碼的任何人都可以使用OpenJDK源代碼對以下與上述代碼段相關的問題進行解釋嗎? 我認為ObjectMonitor , BasicLock , Synchronizer類與該解釋更為相關。
MyWorker
對象實例或Object lock1
還是兩者都適用? 因為JSL和Bill Vennams的解釋描繪了每個對象都與一個監視器相關聯。 MyWorker
對象實例如何監控是為創建MyWorker
對象實例? Object lock1
創建鎖對象 為哪個對象實例創建監視對象?
每個 Java對象也是一個監視對象 ,包括反射對象,因此您的代碼至少具有以下內容:
MyWorker
類對象 Random
類對象 Object
List
類對象 Integer
類對象 ArrayList
類對象 random
Random
實例 lock1
Object
實例 lock2
Object
實例 list1
ArrayList
實例 list2
ArrayList
實例 Thread
實例分配給局部變量t1
Thread
實例分配給局部變量t2
add(random.nextInt(100))
時通過自動裝箱創建的每個Integer
實例 它適用於MyWorker對象實例或對象lock1還是兩者都適用?
都
如果用於MyWorker對象實例,如何為MyWorker對象實例創建監視器?
我們如何為參考對象Object lock1創建鎖對象
監視器的鎖定對象實際上如何鎖定線程?
取決於JVM內部。 沒有唯一的答案,“徹底的解釋”超出了本網站的范圍。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.