自旋鎖
線程被阻塞后便進(jìn)入內(nèi)核Linux調(diào)度狀態(tài),這個(gè)會(huì)導(dǎo)致系統(tǒng)在用戶態(tài)和內(nèi)核態(tài)來回切換搭儒,嚴(yán)重影響鎖的性能
緩解上述問題的辦法便是自旋穷当,其原理是:當(dāng)發(fā)生爭(zhēng)用時(shí)提茁,若Owner線程能在很短的時(shí)間內(nèi)釋放鎖,則那些正在用線程可以稍微等一等(自旋)馁菜,在Owner線程釋放鎖后茴扁,爭(zhēng)用線程可能會(huì)立即得到鎖,從而便面了系統(tǒng)的阻塞汪疮。但Owner運(yùn)行的時(shí)間可能會(huì)超出了臨界值峭火,爭(zhēng)用線程自旋一段時(shí)間后還無法獲得鎖,這時(shí)爭(zhēng)爭(zhēng)用線程則會(huì)停止自旋進(jìn)入阻塞狀態(tài)(后退)智嚷÷敉瑁基本思路就是就是自旋,不成功再阻塞盏道;盡量降低阻塞的可能性稍浆,這對(duì)那些執(zhí)行時(shí)間很短的代碼塊來說有非常重要的性能提升。自旋鎖有個(gè)貼切的名字猜嘱,自旋指數(shù)后退鎖衅枫,,也即復(fù)合鎖朗伶,很顯然弦撩,自璇在多個(gè)處理器上才有意義。
還有個(gè)問題是腕让,線程自旋時(shí)做些啥孤钦?其實(shí)啥都不做,可以執(zhí)行幾次for循環(huán)纯丸,可以執(zhí)行幾條空的匯編指令偏形,目的是占著cpu不放,等待獲得鎖的機(jī)會(huì)觉鼻,所以說自旋是把雙刃劍俊扭,如果旋的時(shí)間過長(zhǎng)會(huì)影響整體性能,時(shí)間過短又達(dá)不到延遲阻塞的目的坠陈。顯然萨惑,自選的周期選擇顯得非常重要,但這與操作系統(tǒng)仇矾,硬件體系庸蔼、系統(tǒng)的負(fù)載等諸多場(chǎng)景相關(guān),很難選擇贮匕,如果選擇不當(dāng)姐仅,不但性能得不到提高,可能還會(huì)下降,因此大家普遍認(rèn)為自旋鎖不具備可擴(kuò)展性掏膏。
偏向鎖
偏向鎖主要解決無競(jìng)爭(zhēng)下的鎖的性能問題劳翰??
現(xiàn)在幾乎所有的鎖都是可重入的馒疹,也即已經(jīng)獲得鎖的線程可以多次鎖住/解鎖監(jiān)視對(duì)象佳簸,按照之前的hotspot設(shè)計(jì),每次加鎖/解鎖都會(huì)涉及到一些CAS操作(比如對(duì)于等待隊(duì)列的CAS操作)颖变,CAS操作會(huì)延遲本地調(diào)用生均,因此偏向鎖的想法是一旦線程第一次獲得監(jiān)視對(duì)象,之后讓監(jiān)視對(duì)象偏向這個(gè)線程悼做,之后的多次調(diào)用則可以避免CAS操作疯特,說白了就是置一個(gè)變量,如果發(fā)現(xiàn)為true則無需再更重加鎖/解鎖的流程肛走。
CAS和SMP架構(gòu)
CAS為什么會(huì)引入本地延遲?這里從SMP對(duì)稱多處理器架構(gòu)說起录别,下面大概說明了SMP的結(jié)構(gòu):
其意思是所有的CPU會(huì)共享一條系統(tǒng)總線BUS朽色,靠此總線連接主存,每個(gè)核都有自己的一級(jí)緩存组题,各核相對(duì)于BUS對(duì)稱分布葫男,因此這種解雇稱為對(duì)稱多處理器
CAS的全稱為Compare and swap,一條CPU的原子指令崔列,器作用是讓CPU比較后原子地更新某個(gè)位置的值梢褐,經(jīng)過調(diào)查發(fā)現(xiàn),其實(shí)現(xiàn)方式基于硬件平臺(tái)的匯編指令赵讯,就是說CAS是靠硬件實(shí)現(xiàn)的盈咳,JVM只是封裝了匯編調(diào)用,那些AtomicInteger類便是使用了這些封裝后的接口
cache一致性考驗(yàn)边翼,當(dāng)很多線程共享一個(gè)對(duì)象的情況下鱼响,即物理層面是很多cpu核通過總線修改對(duì)象內(nèi)存的數(shù)據(jù),那么總線的通信能力將成為瓶頸组底,總線引起的總線風(fēng)暴丈积,這就是所謂的本地延遲,本質(zhì)上偏向鎖就是為了消除CAS债鸡,降低Cache一致性流量
synchronzed的底層實(shí)現(xiàn)主要依靠Lock-Free的隊(duì)列江滨,基本思路是自旋后阻塞,競(jìng)爭(zhēng)切換后繼續(xù)競(jìng)爭(zhēng)鎖厌均,稍微犧牲了公平性唬滑,獲得了高吞吐。