synchronized底層實現原理
進入時:monitorenter
每個物件有一個監視器鎖(monitor)。當monitor被佔用時就會處於鎖定狀態,執行緒執行monitorenter指令時嘗試獲取monitor的所有權,過程如下:
1、如果monitor的進入數為0,則該執行緒進入monitor,然後將進入數設定為1,該執行緒即為monitor的所有者。
2、如果該執行緒已經佔有該monitor,又重新進入,則進入monitor的進入數加1。
3、如果其他執行緒已經佔用了monitor,則該執行緒進入阻塞狀態,直到monitor的進入數為0,再重新嘗試獲取monitor的所有權。
退出時:monitorexit
執行monitorexit的執行緒必須是objectref所對應的monitor的所有者。
指令執行時,monitor的進入數減1,如果減1後進入數為0,那執行緒退出monitor,不再是這個monitor的所有者。其他被這個monitor阻塞的執行緒可以嘗試去獲取這個
monitor 的所有權。
通過這兩段描述,我們應該能很清楚的看出synchronized的實現原理,synchronized的語義底層是通過一個monitor的物件來完成。
其實wait/notify等方法也依賴於monitor物件,這就是為什麼只有在同步的塊或者方法中才能呼叫wait/notify等方法,否則會丟擲java.lang.IllegalMonitorStateException的異常的原因。
當synchronized加在方法前時:
從反編譯的結果來看,方法的同步並沒有通過指令monitorenter和monitorexit來完成(其實也可以通過這兩條指令來實現)。
相對於普通方法,其常量池中多了ACC_SYNCHRONIZED標示符。
JVM就是根據該標示符來實現方法的同步的:當方法被呼叫時,呼叫指令將會檢查方法的 ACC_SYNCHRONIZED 訪問標誌是否被設定,如果設定了,執行執行緒將先獲取monitor,獲取成功之後才能執行方法體,方法執行完後再釋放monitor。在方法執行期間,其他任何執行緒都無法再獲得同一個monitor物件。 其實本質上沒有區別,只是方法的同步是一種隱式的方式來實現,無需通過位元組碼來完成。
---------------------
轉自:https://blog.csdn.net/hbtj_1216/article/details/77773292