前提:
首先要鋪墊幾個前置的知識:
Java中的鎖如sychronize鎖是對象鎖,Java對象頭中具有標識位,當對象鎖升級為重量級鎖時,重量級鎖的標識位會指向監視器monitor,
而每個Java對象關聯唯一的監視器monitor,因為該關系,Java對象可以做synchronize鎖的鎖對象,也叫做監視器鎖或者是對象鎖
1.synchronized 關鍵字修飾方法
Javap反編譯后查看字節碼指令如下:
同步方法,JVM使用ACC_SYNCHRONIZED標識來實現。即JVM通過在方法訪問標識符(flags)中加入ACC_SYNCHRONIZED來實現同步功能。
同步方法是隱式的。當一個線程訪問方法時,會去檢查是否存在ACC_SYNCHRONIZED標識,如果存在,則先要獲得對應的monitor鎖,然后執行方法。當方法執行結束(不管是正常return還是拋出異常)都會釋放對應的monitor鎖。如果此時有其他線程也想要訪問這個方法時,會因得不到monitor鎖而阻塞。當同步方法中拋出異常且方法內沒有捕獲,則在向外拋出時會先釋放已獲得的monitor鎖;
2.synchronized修飾同步代碼塊

每個對象都會與一個monitor相關聯,當某個monitor被擁有之后就會被鎖住,當線程執行到monitorenter指令時,就會去嘗試獲得對應的monitor。步驟如下:
- 每個monitor維護着一個記錄着擁有次數的計數器。未被擁有的monitor的該計數器為0,當一個線程獲得monitor(執行monitorenter)后,該計數器自增變為 1 。
- 當同一個線程再次獲得該monitor的時候,計數器再次自增;
- 當不同線程想要獲得該monitor的時候,就會被阻塞。
- 當同一個線程釋放 monitor(執行monitorexit指令)的時候,計數器再自減。當計數器為0的時候。monitor將被釋放,其他線程便可以獲得monitor。
參考: