Java并發(fā)

并發(fā)的挑戰(zhàn)

上下文切換: 是消耗資源的操作,進入內(nèi)核態(tài)需要

資源限制 : ?I/O 數(shù)據(jù)庫,cpu核數(shù)

死鎖 :等待不到需要的資源

volatile

內(nèi)存語義

當(dāng)寫一個volatile變量時,JMM會把該線程對應(yīng)的本地內(nèi)存中的共享變量值刷新到主內(nèi)存中。當(dāng)讀一個volatile變量時,JMM會把該線程對應(yīng)的本地內(nèi)存置為無效,線程接下來將從主內(nèi)存中讀取共享變量

硬件實現(xiàn)

使用硬件指令當(dāng)前緩存行刷入主內(nèi)存

是其他緩存中此變量的緩存行無效

使得讀操作需要重新從主內(nèi)存加載此變量

適用場景

只有一個線程對volatile變量寫

Synchronized

鎖的對象

Java中的每一個對象都可以作為鎖。

對于同步方法,鎖是當(dāng)前實例對象。

對于靜態(tài)同步方法,鎖是當(dāng)前對象的Class對象。

對于同步方法塊,鎖是Synchonized括號里配置的對象

實現(xiàn)

同步方法

使用 ACC_SYNCHRONIZED 標(biāo)記符隱示的實現(xiàn),原理是通過方法調(diào)用指令檢查該方法在常量池中是否包含 ACC_SYNCHRONIZED 標(biāo)記符,JVM 要求線程在調(diào)用之前請求鎖

同步代碼塊

JVM通過monitorenter和monitorexist指令實現(xiàn)同步鎖的獲取和釋放功能

monitorenter指令是在編譯后插入到同步代碼塊的開始位置

monitorexit指令是插入到方法結(jié)束處和異常處

JVM要保證每個monitorenter必須有對應(yīng)的monitorexit與之配對

任何對象都有一個monitor與之關(guān)聯(lián),當(dāng)且一個monitor被持有后,它將處于鎖定狀態(tài)

線程執(zhí)行monitorenter指令時,將會嘗試獲取對象所對應(yīng)的monitor的所有權(quán),即嘗試獲得對象的鎖

線程執(zhí)行monitorexit指令時,將會將進入次數(shù)-1直到變成0時釋放監(jiān)視器

同一時刻只有一個線程能夠成功,其它失敗的線程會被阻塞,并放入到同步隊列中,進入BLOCKED狀態(tài)

虛擬機做的鎖優(yōu)化

1.鎖消除,消除無謂的鎖

2.鎖粗化,合并太小粒度的加鎖

3.鎖自旋,自適應(yīng)自旋

4.鎖膨脹

鎖膨脹

Java對象頭

偏向鎖

為了在無多線程競爭的情況下盡量減少不必要的輕量級鎖執(zhí)行路徑

,而偏向鎖則是在只有一個線程執(zhí)行同步塊時進一步提高性能



輕量級鎖

目的是沒有多線程競爭的前提下,減少傳統(tǒng)的重量級鎖

輕量級鎖是為了在線程交替執(zhí)行同步塊時提高性能



重量級鎖實現(xiàn)

Monitor Record結(jié)構(gòu)

MonitorRecord(統(tǒng)一簡稱MR)是Java線程私有的數(shù)據(jù)結(jié)構(gòu),每一個線程都有一個可用MR列表,同時還有一個全局的可用列表

一個被鎖住的對象都會和一個MR關(guān)聯(lián)(對象頭的MarkWord中的LockWord指向MR的起始地址)

MR中有一個Owner字段存放擁有該鎖的線程的唯一標(biāo)識,表示該鎖被這個線程占用

Monitor Record工作機理


線程如果獲得監(jiān)視鎖成功,將成為該監(jiān)視鎖對象的擁有者

在任一時刻,監(jiān)視器對象只屬于一個活動線程(Owner)

擁有者可以調(diào)用wait方法自動釋放監(jiān)視鎖,進入等待狀態(tài)

AQS

原子操作

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容