java同步機制synchronized的一些學習
最近看JVM的時候,看到了java虛擬機器的位元組碼指令,其中的同步指令,來做一些總結:
Java虛擬機器可以支援方法級的同步和方法內部一段指令序列的同步,這兩種同步結構都是使用管程(Monitor,更常見的是直接將它稱為“鎖”)來實現的。
方法級的同步是隱式的,無須通過位元組碼指令來控制,它實現在方法呼叫和返回操作之中。
虛擬機器可以從方法常量池中的方法表結構中的ACC_SYNCHRONIZED訪問標誌得知一個方法是否被宣告為同步方法。
當方法呼叫時,呼叫指令將會檢查方法的ACC_SYNCHRONIZED訪問標誌是否被設定,如果設定了,執行執行緒就要求先成功持有管程,然後才能執行方法,最後當方法完成(無論是正常完成還是非正常完成)時釋放管程。
在方法執行期間,執行執行緒持有了管程,其他任何執行緒都無法再獲取到同一個管程。
如果一個同步方法執行期間丟擲了異常,並且在方法內部無法處理此異常,那這個同步方法所持有的管程將在異常拋到同步方法邊界之外時自動釋放。
同步一段指令集序列通常是由Java語言中的synchronized語句塊來表示的,Java虛擬機器的指令集中有monitorenter和monitorexit兩條指令來支援synchronized關鍵字的語義,正確實現synchronized關鍵字
需要Javac編譯器與Java虛擬機器兩者共同協作支援。
monitorenter,monitorexit是2個關鍵的指令,比較長,可以自己用筆在紙上寫一寫。進入和退出?是這樣理解的嗎?接著看!
void onlyMe(Foo f) {
synchronized(f) {
doSomething();
}
}
編譯後的位元組碼
編譯器必須確保無論方法通過何種方式完成,方法中呼叫過的每條monitorenter指令都必須有其對應的monitorexit指令,而無論這個方法是正常結束還是異常結束。
編譯之後的二進位制檔案可以看到,為了保證在方法異常完成時monitorenter和monitorexit指令依然可以正確配對執行,編譯器會自動產生一個異常處理程式,這個異常處理程式宣告可處理所有的異常,它的目的就是用來執行monitorexit指令。
上面這種方式是synchronized的加在同步程式碼塊上的。
還有一種是synchronized加在方法上的:可以參考部落格https://blog.csdn.net/qq_36934826/article/details/95978700