synchronized關鍵字
synchronized(同步),也就是用於進行線程同步的關鍵字,共三種使用情況。
一、用於修飾static方法時
- 此時同步使用的是:class lock : 類鎖
- 同步的範圍包括,
該類的所有的靜態方法
和其實例對象的所有實例對象方法
。
public static synchronized void synMethod() {}
二、用於修飾對象方法時
- 此時同步使用的是:object lock:實例對象鎖
- 同步的範圍包括,屬於
當前實例對象
的所有非static方法
(對象方法)。
public synchronized void synMethod() {}
三、用於修飾方法塊時
synchronized(對象/類) {
// ...
}
- 此時同步使用的鎖根據參數不同而不同。對象就是對象鎖,類就是類鎖。
補充理解:
-
鎖的範圍如何理解?
答:同步其實考慮的是對資源操作的同步, 例如。如果是類鎖,首先看,類有哪些資源
--> 類有static成員變量。然後,哪些方法能操作其擁有的資源
--> 類方法和該類的所有實例的對象方法。所以鎖的範圍就包括這些方法。 -
synchronized的底層實現原理是什麼?
答:簡單的來說,通過使用jvm所實現的monitorenter指令
和monitorexit指令
。來操作monitor(也就是一把鎖)
對象的獲取和釋放來實現。(每個實例對象都有一把鎖(monitor)與之對應)。- 同步代碼塊:直接的通過
monitorenter指令
和monitorexit指令
實現。[在同步代碼塊處編譯成字節碼後,該部分會自動加上異常處理,也就是加了個finally,finnlly裏面執行monitorexit指令
,出現異常時也能成功的釋放鎖,否則可能會死鎖] - static和非static同步方法通過:
ACC_SYNCHRONIZED標誌
實現(該標誌最終也是和同步代碼塊的實現方式一樣)。
- 同步代碼塊:直接的通過
-
monitor對象,在哪?
每個對象在堆中存儲着,實例對象由三部分組成:對象頭
、實例變量
和填充數據
。其中對象頭
結構中,有一部分就存儲着其,monitor對象在棧中的地址。
參考資料:Java synchronized 詳解 : http://www.sohu.com/a/273749069_505779