來源
https://www.imooc.com/learn/1086
作用
同步方法支持一種簡單的策略來防止線程干擾和內存一致性錯誤,如果一個對象對多個線程可見,則對該對象變量的所有讀取或寫入都是通過同步方法完成的。
即:能夠保證在同一時刻最多只有一個線程執行該段代碼,達到保證並發安全的效果。
-
Synchronized是Java的關鍵字,被Java原生支持。
-
是最基本的互斥同步手段。
用法
- 對象鎖
- 方法鎖(鎖對象為this當前實例對象)
- 同步代碼鎖(自己指定鎖對象)
- 類鎖:只有一個Class對象
- synchronized修飾靜態方法
- 指定鎖為Class對象
多線程訪問同步方法的7種情況
1、兩個線程同時訪問一個對象的同步方法
串行執行
2、兩個線程訪問的是兩個對象的同步方法
並行方法,不是一個對象。
3、兩個線程訪問的是synchronized的靜態方法
串行執行,只有一個Class對象
4、同時訪問同步方法和非同步方法
並行執行
5、訪問同一個對象的不同的普通同步方法
串行,this是同一個
6、同時訪問靜態synchronized和非靜態的synchronized方法
並行執行,鎖對象不是同一個
7、方法拋出異常后,釋放鎖
synchronized會自動釋放,Lock等不會
三個核心思想
- 一把鎖只能同時被一個線程獲取,沒有拿到鎖的線程必須等待(對應第1、5種情況)
- 每個實例都對應有自己的一把鎖,不同實例之前互不影響;
例外:鎖對象是*.class以及synchronized修飾的是static方法的時候,所有對象共用同一把類鎖(對應2、3、4、6種情況) - 無論是方法正常執行完畢或者方法拋出異常,都會釋放鎖(對應第7種情況)
性質
1、可重入:
同一個線程的外層函數獲取鎖后,內層函數可以直接再次獲取該鎖。
2、不可中斷
原理
1、加鎖和釋放鎖的原理:Monitor
2、可重入原理:加鎖次數計數器
3、可見性原理:內存模型圖
缺點
1、效率低
- 鎖的釋放情況少
- 視圖獲取鎖時不能設置超時時間
- 不能中斷一個正在視圖獲取鎖的線程
2、靈活度較差
- 加鎖和釋放鎖的時機單一
- 每個鎖僅有單一的對象
3、無法知道是否成功獲取到鎖
注意點
1、鎖對象不能為空、作用域不宜過大、避免死鎖
2、盡量使用JUC包下的類,再考慮Synchronized,再考慮Lock