簡體   English   中英

Java對象鎖定和監視器創建如何在JVM內部發生

[英]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實現根據該場景在內部進行對象鎖定。 我期待一個低水平的解釋。

我花了幾天的時間研究這個主題,卻找不到深入的解釋。 這些是我經歷的一些發現:

  • 這個stackoverflow問題Java鎖概念在內部如何工作? 但是我無法在答案中找到詳盡的解釋。
  • JLS 17.1提供了有關監視器如何在較高級別上工作的語言說明,但沒有“內部發生”的內容。

這些方法中最基本的是同步,它是使用監視器實現的。 Java中的每個對象都與一個監視器關聯,線程可以鎖定或解鎖監視器。 一次只能有一個線程在監視器上保持鎖。 嘗試鎖定該監視器的所有其他線程將被阻止,直到它們可以在該監視器上獲得鎖定為止。 線程t可以多次鎖定特定的監視器。 每次解鎖都會逆轉一次鎖定操作的效果。

在Java虛擬機中,每個對象和類在邏輯上都與監視器關聯。 對於對象,關聯的監視器將保護對象的實例變量。 對於類,監視器將保護類的類變量。 如果對象沒有實例變量,或者一個類沒有類變量,則關聯的監視器將不保護任何數據。

為了實現監視器的互斥功能,Java虛擬機將鎖(有時稱為互斥鎖)與每個對象和類關聯。 鎖就像特權,一次只能有一個線程“擁有”。 線程無需獲取鎖即可訪問實例或類變量。 但是,如果某個線程確實獲得了鎖,則只有擁有該鎖的線程將其釋放后,其他線程才能在同一數據上獲得鎖。 (“鎖定對象”是獲取與該對象關聯的監視器。)

我知道在指令集級別如何使用monitorentermonitorexit操作碼來管理同步語句。 但是我試圖通過JVM源代碼級別更深入地了解。 但是,由於我在源代碼中有很多不足之處,因此我仍在努力將OpenJDK源代碼與通過上述鏈接找到的高級解釋進行映射。

因此,熟悉OpenJDK源代碼的任何人都可以使用OpenJDK源代碼對以下與上述代碼段相關的問題進行解釋嗎? 我認為ObjectMonitorBasicLockSynchronizer類與該解釋更為相關。

  1. 為哪個對象實例創建監視對象? 它適用於MyWorker對象實例或Object lock1還是兩者都適用? 因為JSL和Bill Vennams的解釋描繪了每個對象都與一個監視器相關聯。
  2. 如果它是MyWorker對象實例如何監控是為創建MyWorker對象實例?
  3. 我們如何為參考對象Object lock1創建鎖對象
  4. 監視器的鎖定對象實際上如何鎖定線程?

為哪個對象實例創建監視對象?

每個 Java對象也是一個監視對象 ,包括反射對象,因此您的代碼至少具有以下內容:

  • MyWorker類對象
  • Random類對象
  • Class對象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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM