自旋鎖和自適應(yīng)自旋鎖
為何引入
互斥同步最大的性能消耗在于阻塞的實(shí)現(xiàn)泡垃。即線程的掛起和喚醒必須轉(zhuǎn)入內(nèi)核態(tài)中實(shí)現(xiàn)幌甘,線程的切換即內(nèi)核態(tài)和用戶態(tài)的切換給并發(fā)性能帶來了很大的消耗。
針對場景
假設(shè)某個線程所持有互斥鎖的時間很短须板。
這樣我們可以讓等待鎖的線程不進(jìn)行休眠榛鼎,而進(jìn)行自旋(比如循環(huán)100次)逃呼,這樣的做法避免了線程的切換。
如果某些線程鎖持有鎖的時間很長這樣做就不行了者娱。
自旋鎖的優(yōu)化--自適應(yīng)自旋鎖
即優(yōu)化每次自旋的時間抡笼。我們可以根據(jù)上一次這個互斥鎖等待的時間以及線程的狀態(tài)等信息,來決定此次是否自旋以及自旋的時間黄鳍。這樣自旋的時間就變成動態(tài)的了推姻。
額外
自旋鎖自1.6開始后默認(rèn)就是開啟的。
鎖清除
為何引入
在一些代碼中加入了互斥同步鎖际起,但實(shí)際上并不可能存在同步現(xiàn)象拾碌。我們需要將這些互斥同步鎖清除掉吐葱。
針對場景
鎖清除現(xiàn)象發(fā)生在即時編譯器運(yùn)行時街望。
如何判定代碼中的互斥同步鎖是多余的呢校翔?
主要依據(jù):逃逸技術(shù)。--即在一段代碼中灾前,發(fā)現(xiàn)堆中的所有數(shù)據(jù)都不會逃逸出去而被其他線程訪問防症,則就可認(rèn)為它們是線程私有的。
鎖粗化
為何引入
原則上我們是希望加鎖的代碼塊越小越好哎甲。但如果一段代碼中頻繁地對某個對象進(jìn)行加鎖和解鎖蔫敲。這樣也會導(dǎo)致消耗性能。
針對場景
當(dāng)虛擬機(jī)檢測到一段代碼頻繁地對同一個對象進(jìn)行加鎖和解鎖時炭玫,就會將鎖范圍擴(kuò)大到這段代碼之外奈嘿,進(jìn)行一次加鎖和解鎖就好了。
輕量鎖
針對場景
對于大部分的鎖吞加,在整個同步周期內(nèi)都不存在競爭裙犹。
--這胡話的意思是:一段代碼在被某個線程上鎖到解鎖的過程中不會存在其他線程來欲訪問這段代碼。
具體優(yōu)化
- 加鎖:當(dāng)前線程執(zhí)行CAS操作衔憨。如果成功則繼續(xù)執(zhí)行同步代碼叶圃,失敗說明有其他線程占有。如果有兩個線程爭用同一個鎖践图,則輕量鎖不再生效掺冠,膨脹為重量級鎖。
- 解鎖:也是通過使用CAS操作來完成码党。
這里說一下:
- 輕量鎖是可以膨脹為重量級鎖的
- 輕量鎖之所以高效德崭,是因?yàn)榧渔i和解鎖只使用了CAS操作而不是使用系統(tǒng)互斥量。兩者的性能差別很大揖盘。
- 在有互斥鎖的競爭下眉厨,輕量鎖的效率很低。因?yàn)槌耸褂没コ饬客膺€額外加了CAS操作扣讼。
- 具體的CAS操作這里就不多說了缺猛。
偏向鎖
針對場景
- 偏向鎖的“偏”是指偏向第一個獲得鎖的線程,如果接下來的過程中椭符,沒有其他線程獲得鎖荔燎,則第一個線程將永遠(yuǎn)無需做同步操作。
- 輕量鎖是在無競爭狀態(tài)在使用CAS來代替互斥量销钝,而偏向鎖是在無競爭狀態(tài)在把整個同步都消除掉有咨,連CAS都省了。
- 既然無需CAS操作蒸健,是不是啟用一定會提高效率座享。其實(shí)并不是婉商,如果鎖總是被不同線程訪問,那么偏向鎖就是多余的渣叛。
- 如果偏向鎖無效之后丈秩,可以膨脹為輕量鎖。
總結(jié)
- 自旋鎖淳衙、鎖清除蘑秽、鎖粗化都是默認(rèn)開啟的,他們的存在會提高效率箫攀。
- 偏向鎖和輕量鎖是在特殊的場景下肠牲,才可以提高性能。否則還會降低性能靴跛。
- 偏向鎖可以膨脹為輕量鎖缀雳,輕量鎖可以膨脹為重量級鎖。不可反向膨脹梢睛。