歷史最優久的使用最方便的線程同步的關鍵字。必須點贊
一、synchronized 特性
-
同一時刻只有一個線程訪問臨界資源
-
其它未獲取到鎖執行權的線程必須排隊等待
-
保證共享資源的原子性、可見性和有序性
-
進入synchronized範圍內自動加鎖,synchronized作用域外鎖自動消除,即使異常也會釋放鎖
-
簡單方便(不需要人工釋放鎖)
-
jdk1.6後性能做了很大優化
二、synchronized用法
作用: 所有訪問該對象實例該方法的線程,必須排隊執行
如: synchronized public void add(){
}
作用: 所有采用類名.方法名訪問的線程, 必須排隊執行
如: synchronized public static void add(){
}
作用: 所有訪問到該表達式的線程,必須排隊執行
synchronized(表達式){
}
表達式可以是:
a. this 表示該對象,僅適用於非靜態方法的情況
b. 類名.class 適用於靜態方法和非靜態方法
c. 對象實例 適用於靜態方法和非靜態方法
d. 成員變量 適用於靜態方法和非靜態方法
三、
synchronized原理
synchronized的底層實現原理都是通過對象頭裏面的monitor(監視器鎖)來實現的。每個對象頭裏面都有一個指針指向monitor,monitor中又包含有訪問計數器,能否進入是根據計數器值來判斷的。
同步代碼塊是通過monitorenter、monitorexit來控制。 字節碼指令如下, 操作原理:
1、當訪問到monitorenter時, 當前線程會嘗試獲取該對象的monitor所有權
獲取所有權的依據是monitor的計數器值是否爲0, 爲0則獲取到了,同時將計數器值 +1
2、如果已獲取到monitor所有權, 則直接將計數器 +1並進入運行指令階段
3、如果沒有嘗試獲取該對象的monitor持有權,會進入等待隊列進行阻塞
同步方法是通過方法常量池中的方法表關鍵字來控制, 如果用synchronized修改方法,那麼常量池裏面會有ACC_SYNCHRONIZEDR進行修飾。
當線程訪問加了synchronized的方法時, 會去判斷是否有ACC_SYNCHRONIZED標識,
1、如果有該標識, 當前線程會嘗試獲取該對象的monitor所有權
獲取所有權的依據是monitor的計數器值是否爲0, 爲0則獲取到了,同時將計數器值 +1
2、如果已獲取到monitor所有權, 則直接將計數器 +1並進入運行指令階段
3、如果沒有嘗試獲取該對象的monitor持有權,會進入等待隊列進行阻塞
四、synchronized可重入性
可重入性也是依據是否可獲取monitor持有權來判斷。