synchronized底層實現monitor詳解


二、ObjectMonitor 結構

前面講到 java.lang.Object 類定義了 wait(),notify(),notifyAll() 方法。 這些都是 native方法,底層是C++來實現的。 這些方法的具體實現,依賴一個叫做ObjectMonitor模式實現,這是JVM內部C++實現的機制。

這里有幾個比較重要的字段

2.1 _owner 指向持有ObjectMonitor對象的線程地址。

2.2 _WaitSet 存放調用wait方法,而進入等待狀態的線程的隊列。

2.3 _EntryList 這里是等待鎖block狀態的線程的隊列。

2.4 _recursions 鎖的重入次數。

2.5 _count 線程獲取鎖的次數。

三、 Monitor 上鎖 釋放鎖

3.1 上鎖過程

3.1.1 線程獲取資源對象的鎖,判斷 _owner是否為空。這里操作是通過 CAS操作:比較和交換(Conmpare And Swap),比較新值和舊值的不同,替換,這里會發生ABA問題,接下來文章會詳細說明。

3.1.2 如果 _owner為null ,直接把其賦值,指向自己, _owner = self ,同時把重入次數 _recursions = 1, 獲取鎖成功。

3.1.3 如果 _self == cur 和當前線程一致,說明是重入了, _recursions++ 即可

3.1.4 線程進入對象資源,處理。 同時等待當前線程的釋放信號,期間一致持有對象資源的鎖。

3.2 釋放鎖

3.2.1 通過 ObjectMonitor::exit 退出

3.2.2 把線程插入到_EntryList中 _recursions--

3.2.3 再次從 _EntryList 中取出線程

3.2.4 調用unpark退出

 

在我們分析synchronized關鍵字底層信息時,其中談到了Monitor對象,它是由C++來實現的,那,到底它長啥樣呢?我們在編寫同步代碼時完全木有看到該對象的存在,所以這次打算真正來瞅一下它的真正面目,而對於這個Hospot代碼JDK是並沒有開源的,但是社區版本的JDK是開源了,在openjdk上可以閱讀得到,所以下面先到openjdk上瞅一下:

所以點擊一下它:

點擊一下:

 

然后點擊左側的browser方便我們瀏覽代碼:

然后定位到這個路徑:

然后點擊runtime/,

 

其中,我們要想看到Monitor對象的源代碼就在其中,如下:

 

 其中.hpp是c++的頭文件,其具體的實現是以cpp中,接下來就得打開它們來看我們想了解的東東了,是不是很刺激?對於上一次理論中提到了兩個東東:

那咱們從源碼中來看一下具體都表現為啥,首先先來看一下ObjectMonitor.hpp:

接下來就可以看到ObjectMonitor的類聲明了:

 

 其實對就對應於:

 

 接下來挑里面的重點內容瞅一下:

接下來看一下它的成員變量:

那看一下_WaitSet的定義:

再看一下_EntryList的定義:

另外在上一個理論中提到了:

 

其實也在底層有定義,如下:

看一下它的定義:

另外上理論中還提到了它:

其實也有對應:

繼續來看其它的一個成員變量:

 

 

 

對於wait()和notify()的底層細節到底是啥樣的呢?下面還是先來到openjdk中來打開ObjectMonitor.hpp,其中它里面有一個很重要的類:

然后我們要分析的wait()和notify()是在它的cpp實現文件中,所以打開ObjectMonitor.cpp來直奔主題:

其中我們在Java層看到的wait()方法的最終實現就是這個cpp中的這個方法:

先縱覽一下該方法的實現,代碼量比較多,有將近200多行的代碼,全部看通是不可能的,挑重點的來看:

 

而Self其實是一個線程:

 

所以這句話的是將線程包裝成了ObjectWaiter對象了:

另外會將狀態改為等待狀態:

 

另外,在上次的理論中我們知道在調用了wait()之后,會將其加入到WaitSet當中,如:

 

那么。。具體對應的底層代碼在哪呢?看下面:

好,下面來瞅一下它的具體實現:

再回到wait()方法繼續,其中可以看到有自旋鎖的東東:

 

下面簡單的縱覽一下它:

好,下面再來觀測一下notify()方法的細節:

 

 

 咱們看一下DequeueWaiter()方法是怎么實現的:

 

回到主流程:

其實在notify()的官網中也有類似的說明:

 

而文檔中提到的“具體實現”其實就是如我們看到cpp中這塊的代碼,不同的策略其實現也不一樣。

照我們之前的理論來說,喚醒的線程會被放到EntryList當中:

 

 在notify()代碼中也能看到:

然后最后會看到有一個這個代碼:

以上就是從底層c++的角度來審視我們在java上調用的wait()和notify()的具體細節,雖說大致看了一下主流程,實際工作也沒啥大的作用,但是!!!對我們的更深入的理解起到了非常重要的作用,畢境可以讓你能更加自信的用Java的這些API。

 

轉載:https://www.cnblogs.com/webor2006/p/11443392.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM