官方解釋,別人翻譯的:
同步方法的運行是隱式的,類似於jvm對於方法的引用和返回的支持。同步方法通過在運行常量池裏method_info數據結構中的ACC_SYNCHRONIZED標籤來標註。
如果一個線程發現調用的方法有ACC_SYNCHRONIZED標記,那麼線程的執行過程就變成:獲取monitor對象,調用方法,釋放monitor對象。
在某個線程持有monitor對象時,如果其他線程也想獲取該對象,則會別阻塞。
如果一個同步方法執行過程中發生異常,而且方法自己沒有處理,那麼在異常被向外拋時,線程也會自動釋放monitor對象。
1.使用方式
a.普通方法,上鎖的對象是類實例,反編譯後字節碼中會有ACC_SYNCHRONIZED關鍵字
b .靜態方法,上鎖的對象是類對象,和上面差不多
c.靜態代碼塊,自定義鎖的對象,在代碼塊的前後會有monitorenter、monitorexit關鍵字,標識計數器+1,或者減1
2.存放方式
synchronized使用的鎖對象是存儲在Java對象頭裏的,而對象頭結構
其中Mark Word在默認情況下存儲着對象的HashCode、分代年齡、鎖標記位等以下是32位JVM的Mark Word默認存儲結構:
還有如下可能變化的結構:
Synchronized屬於結構中的重量級鎖,對象的對象頭的鎖信息裏面包含了monitor,每個對象都有一個monitor與之關聯,類似一個管家,獲取鎖本質就是獲取monitor
monitor是由ObjectMonitor(c++)實現的,
結構中幾個重要的字段要關注,_count、_owner、_EntryList、_WaitSet。
count用來記錄線程進入加鎖代碼的次數。
owner記錄當前持有鎖的線程,即持有ObjectMonitor對象的線程。
EntryList是想要持有鎖的線程的集合。
WaitSet 是加鎖對象調用wait()方法後,等待被喚醒的線程的集合。
3.鎖的獲取邏輯
4.鎖升級
5.synchronize原理
6.synchronize和lock
參考:
https://blog.csdn.net/a760352276/article/details/107620307
https://www.cnblogs.com/little-sheep/p/9909111.html 這是厲害