第四章:并發(fā)之共享模型
共享帶來的問題
為什么需要共享cpu
無法利用cpu的情況:sleep诅迷,wait教翩,io操作逮刨,通過分時系統(tǒng)提交cpu的利用率秽晚。即一個時間段內(nèi)多個線程可以獲取cpu資源
java中的體現(xiàn)
問題的產(chǎn)生:線程一對靜態(tài)變量i自加5000次瓦糟,線程二對靜態(tài)變量i自減5000次,最后的i不是0.
問題分析:i++操作在字節(jié)碼層面不是一條指令赴蝇。分為多條指令進行菩浙,在運算時在線程內(nèi)進行運算然后寫到主存,所線程一中計算后的結(jié)果還沒有寫到主存中cpu時間片用完了句伶,線程二讀取到了未被計算的i劲蜻,所以造成這個結(jié)果
[圖片上傳失敗...(image-f598a4-1606228386315)]
臨界區(qū)
[圖片上傳失敗...(image-524999-1606228386315)]
一段代碼塊內(nèi)如果存在對共享資源的多線程讀寫操作,這段代碼塊稱為臨界區(qū)
競太條件
多個線程在臨界區(qū)內(nèi)執(zhí)行考余,由于代碼的執(zhí)行序列不同導(dǎo)致結(jié)果無法預(yù)測先嬉,稱之發(fā)生了競態(tài)條件
解決方法
阻塞式:synchronized,lock
非阻塞式:原子變量
[圖片上傳失敗...(image-a04da6-1606228386315)]
互斥是對于同一資源來說的(靜態(tài)變量i)楚堤,同步只是規(guī)定了線程的執(zhí)行順序
synchronized保證了操作的原子性疫蔓,但并不保證可見性?身冬?衅胀?
synchronized
在修改了本地內(nèi)存中的變量后,解鎖前會將本地內(nèi)存修改的內(nèi)容刷新到主內(nèi)存中酥筝,確保了共享變量的值是最新的滚躯,也就保證了可見性。
[圖片上傳失敗...(image-43fc39-1606228386315)]
方法上的synchronized
[圖片上傳失敗...(image-436c77-1606228386315)]
變量線程安全分析
方法本身是線程私有的嘿歌,安不安全是對于這個方法里操作的資源來說的掸掏,如果這個資源是靜態(tài)變量或者是引用對象等有可能造成線程不安全的問題
成員變量的安全性
[圖片上傳失敗...(image-17d338-1606228386315)]
局部變量的安全性
子類繼承造成的線程安全問題
當子類覆蓋了父類的方法后父類的局部變量會暴漏,方法的訪問修飾符是有意義的搅幅,可以在一定程度上保護方法中的資源安全問題
常見線程類
String阅束,Integer呼胚,StringBuffer茄唐,Random,HashTable蝇更,concurrent包下的類沪编。
也就是說他們的每個方法是原子的,==但是組合在一起不一定是線程安全的==
String類為什么是不可變類
線程安全類方法的組合
實例分析
售票問題
轉(zhuǎn)賬問題
使用的鎖必須是A賬戶和B賬戶同一把鎖年扩,所以將鎖加在方法上是不行的蚁廓,要用Account.class。==使用類鎖只能有兩個賬戶同時轉(zhuǎn)賬厨幻,如果賬戶很多時會造成性能的低下==
Monitor概念
monitor在操作系統(tǒng)中叫做管程