簡介:對多線程可見,保證同一時刻最多隻有一個線程執行代碼,達到線程併發安全,被修飾的代碼保證了可見性、一定程度上的原子性和禁止指令重排序。關鍵是獨佔一個鎖。關鍵字,java原生支持,最基本的互斥同步手段。
如果不使用併發手段的後果:比如兩個線程同時執行a++,最後結果比預期的要少
原因:a++包含三個操作不具有原子性,讀取a值,a+1,然後寫入內存,共分三個步驟搶佔式調度引起,底層原理是java內存模型機制引起。
用法:
對象鎖:方法鎖(默認對象爲this當前實例對象)和同步代碼塊鎖(自己指定鎖對象包括this)
類鎖:指Synchrinized修飾的靜態方法或者代碼塊指定鎖爲Class對象,java類可以用很多對象,只有一個Class對象
鎖不同相互沒有影響--並行而非串行
類鎖可以全局保護,不同的對象實例進來也可以同步執行如New Thrend(class.this1)和
New Thrend(class.this2),同時執行同步代碼塊,對象鎖是並行的而類鎖可以同步執行
多線程訪問同步方法的七種情況
1:兩個線程同時訪問一個對象的同步方法
同一把鎖存在阻塞
2:兩個線程訪問來兩個對象的同步方法
鎖住不同的實例,所以不會阻塞
3:兩個線程訪問的是靜態方法
鎖對象爲Class對象,存在阻塞
4:如果同時訪問同步方法和非同步方法
非同步方法不會受到影響
5:訪問同一個對象的不同的普通同步方法
鎖是一樣的,發生阻塞
6:同時訪問靜態和非靜態的同步方法
兩個鎖不一樣,不受影響,串行
7:方法拋出異常,會釋放鎖
總結:
a:一把鎖只能同時被一個線程獲取,沒有拿到鎖的線程必須等待
b:每一個實例都對應有自己的一把鎖,不同的實例之間相互不影響,但是Class對象鎖,所有對象公用一把鎖
c:無論正常執行完畢還是拋出異常都會釋放鎖
Synchrinized性質:
1.可重入(遞歸鎖):同一線程外層函數獲得鎖之後,內層函數可以直接再獲取該鎖,避免死鎖,提升封裝性,粒度:線程而非調用
2. 獨佔
可重入性質:
1: 同一個方法可重入
2:可重入不要求是同一個方法
3:可重入不要求是同一個類
不可中斷:一旦鎖已經被別人獲得,,如果我想再想獲得,就只能等待或者阻塞,直到別的線程釋放鎖,否則會一直等待下去(與Lock比,可以設置超時時間)
原理
1:加鎖和釋放鎖
現象
內置鎖
等價代碼----Lock
深入JVM字節碼:
概況:java對象頭存儲synchrinized,基於monitor
反編譯:monitorenter開始鎖住代碼塊,monitorexit釋放鎖
Monitorenter:+1獲取鎖,重入再+1,其他線程阻塞
Monitorexit:計數器-1,爲0就失去monitor的所有權,其他線程可以獲取可以獲取鎖
2:可重入原理:每一個對象都有一把瑣,jvm負責跟蹤對象被加鎖的次數
線程第一次給對象加鎖的時候,計數器變爲1,每當相同的線程此對象上再次獲得鎖,計數器會遞增
每當任務離開的時候,計數遞減,每當計數爲0的時候,鎖被完全釋放
3:保證可見性原理:
Java內存模型:1:主內存數據複製副本到工作內存,2更新,3更新後把數據寫入主內存中,一旦被synchrinized修飾,同時只有一個線程修改數據,所以修改對其他線程是可見的,保證線程安全性
缺陷:
效率低:所得釋放情況少,只有當前線程執行結束和發生異常才釋放鎖,試圖獲得時不能設定超時時間,不能中斷一個正在試圖獲得鎖的線程---Lock對比
不夠靈活(讀寫鎖更加靈活):加鎖和釋鎖的時機單一,每個鎖僅有單一的條件(某個對象),可能是不夠的
無法知道是否成功的獲取了鎖
---Lock接口對比
Lock lock =new reenetrylock
lock.lock()
lock.unLock()
lock.tryLock() ----返回boobean
lock.trylock(超時時間)----返回boobean
思考:
1:使用注意點:鎖對象不能爲空、作用域不宜過大(效率低)、避免死鎖
2:如何選擇sync和Lock?
建議:如果可以都不使用,使用併發包中的類,考慮開發效率,出錯機率以及執行效率
3:多線程訪問同步方法的各種具體情況
思考:
1:多個線程等待同一個synchronized鎖的時候,JVM如何選擇下一個獲取鎖的線程,涉及鎖的調度機制
2:sync使得同時只有一個線程可以執行,性能差,如何提高性能,優化鎖的範圍儘可能小,
可以替代,比如讀寫鎖
3:更加靈活的控制鎖的獲取和釋放?
4:什麼是鎖的升級、降級?什麼是JVM裏的輕量級鎖、偏斜鎖、重量級鎖?
總結:
一句話介紹synchronized:
Jvm會自動通過使用monitro來加鎖和解鎖,使鎖住的代碼塊具有原子性操縱,保證只有一個線程可以執行指定的代碼,從而保證線程安全,同時具有可重入和不可中斷的性質
ps:寫的不夠好,如果有不足或者錯誤的地方歡迎留言指正