所有的代碼在單線程時啥寇,都不會出問題。
多線程就有可能出現(xiàn)問題洒扎,多個線程訪問同一個資源辑甜,會導(dǎo)致資源發(fā)生問題。
我們期望在某些代碼統(tǒng)一執(zhí)行袍冷,不被其他線程打斷磷醋。
所有對象都有1把鎖,每個鎖都有各自的計數(shù)器
1难裆、在代碼塊聲明同步 指定對象
2子檀、非靜態(tài)方法上聲明同步 this
3镊掖、靜態(tài)方法上聲明同步 當前類.class
一、線程同步概念
線程同步是指在訪問共享資源時多個線程相互間的協(xié)調(diào)和控制褂痰。
樣例1:
樣例2:偶數(shù)生成器
二亩进、實現(xiàn)線程同步
1、Synchronized使用方式:
同步代碼塊:鎖對象可以自己指定缩歪,任何類型都可以充當鎖對象归薛,多個線程對代碼塊中的代碼要想達到互
斥執(zhí)行的效果,那么多個線程需要共享相同的鎖對象,選取依據(jù)就是只要滿足共享性匪蝙,當下的環(huán)境有有什
么對象就用什么對象
當代碼塊包含了整個方法的內(nèi)容主籍,就可以把synchronized寫在方法上
同步非靜態(tài)方法:鎖對象就是this
同步靜態(tài)方法:鎖對象為當前類.class
2、Synchronized工作機制
只有一個線程持有鎖對象的監(jiān)視器的時候逛球,該線程才能執(zhí)行同步代碼塊中的代碼千元, 同步代碼塊執(zhí)行完之
后,會釋放鎖對象的監(jiān)視器颤绕,同樣一個鎖對象的監(jiān)視器同一時刻幸海,只能被1個線程擁有,鎖對象監(jiān)視器會
有一個計數(shù)器(count)奥务,當一個線程執(zhí)行同步代碼塊的時候物独,會對計數(shù)器,進行判斷氯葬,如果是默認
值挡篓,就進入同步代碼塊,并對計數(shù)器進行自加帚称,執(zhí)行完畢之后官研,計數(shù)器進行自減,如果計數(shù)器不是默認
值世杀,那么表示鎖對象的監(jiān)視器被另外一個線程正在持有阀参,就無法進入
3、釋放鎖對象監(jiān)視器
一個線程能進入同步代碼塊瞻坝,必須持有鎖對象的監(jiān)視器蛛壳,此時,其他線程不能同時持有鎖對象的監(jiān)視
器所刀,必須等待目前持有鎖對象監(jiān)視器的線程釋放鎖對象的監(jiān)視器衙荐。如何釋放:
同步代碼塊執(zhí)行結(jié)束
wait(必須使用在同步代碼塊中)
三、線程協(xié)作:
等待喚醒機制浮创,實現(xiàn)線程間的通信和協(xié)作忧吟,必須建立在互斥的基礎(chǔ)上
wait:交出鎖對象的監(jiān)視器,釋放cpu的使用權(quán)斩披,鎖對象.wait()溜族,wait結(jié)束之后讹俊,線程回到就緒狀態(tài)
notify:喚醒等待當前鎖對象監(jiān)視器的線程之一,鎖對象.notify();
notifyAll: 喚醒等待當前鎖對象監(jiān)視器的所有線程煌抒,鎖對象.notifyAll();
樣例1:
樣例2:
樣例3:
生產(chǎn)者消費者模式
單生產(chǎn)者單消費者
多生產(chǎn)者多消費者模式
四仍劈、線程同步的應(yīng)用:
懶漢式單例模式線程不安全
雙重鎖機制
五、死鎖
多個線程在競爭資源的時候出現(xiàn)了互相等待的情況
sleep 和 wait的區(qū)別
sleep是Thread類中的靜態(tài)方法,wait是Object類中非靜態(tài)方法方法
sleep方法不是必須在同步代碼中調(diào)用,wait必須在同步代碼中調(diào)用
Sleep方法直接通過Thread類名調(diào)用掀泳,wait需要通過同步代碼中的鎖對象調(diào)用
Sleep不會交出鎖對象的監(jiān)視器,wait會交出鎖對象的監(jiān)視器