JUC核心-AQS(AbstractQueuedSynchronizer)簡(jiǎn)析

AQS是什么?

  • AQS 全稱是 AbstractQueuedSynchronizer, 它提供一種依賴于FIFO等待隊(duì)列的構(gòu)建鎖和同步器的框架

  • CAS是什么?

CAS(Compare And Swap),即比較并交換桅锄。是解決多線程并行情況下使用鎖造成性能損耗的一種機(jī)制,CAS操作包含三個(gè)操作數(shù)——內(nèi)存位置(V)样眠、預(yù)期原值(A)和新值(B)友瘤。如果內(nèi)存位置的值與預(yù)期原值相匹配,那么處理器會(huì)自動(dòng)將該位置值更新為新值檐束。否則辫秧,處理器不做任何操作。無(wú)論哪種情況被丧,它都會(huì)在CAS指令之前返回該位置的值具则。CAS有效地說(shuō)明了“我認(rèn)為位置V應(yīng)該包含值A(chǔ)麻裳;如果包含該值铭腕,則將B放到這個(gè)位置券时;否則,不要更改該位置黄选,只告訴我這個(gè)位置現(xiàn)在的值即可蝇摸。

底層實(shí)現(xiàn)

整體結(jié)構(gòu)

  • AQS 的結(jié)構(gòu)大概可總結(jié)為以下 3 部分:

    • 用 volatile 修飾的整數(shù)類型的 state 狀態(tài),用于表示同步狀態(tài)办陷,提供 getState 和 setState, compareAndSetState來(lái)操作同步狀態(tài)貌夕;
    • 提供了一個(gè) FIFO 等待隊(duì)列,實(shí)現(xiàn)線程間的競(jìng)爭(zhēng)和等待民镜,這是 AQS 的核心啡专;其中, 鏈表頭Head和鏈表尾Tail也有volatile修飾。
    • AQS 內(nèi)部提供了各種基于 CAS 原子操作方法制圈,如 compareAndSetState 方法植旧,并且提供了鎖操作的acquire和release方法辱揭。
  • 提供兩種鎖的默認(rèn)實(shí)現(xiàn)方式:

    • 獨(dú)占鎖(Exclusive)
    • 共享鎖(Shared)
  • tryAcquire, tryRelease 都是需要實(shí)現(xiàn)類自己去實(shí)現(xiàn)的方法, 如果不實(shí)現(xiàn)的話,是會(huì)拋出異常UnsupportedOperationException的

  • 用到的設(shè)計(jì)模式-模板模式, 在模板模式(Template Pattern)中病附,一個(gè)抽象類公開定義了執(zhí)行它的方法的方式/模板。它的子類可以按需要重寫方法實(shí)現(xiàn)亥鬓,但調(diào)用將以抽象類中定義的方式進(jìn)行完沪。這種類型的設(shè)計(jì)模式屬于行為型模式。

獨(dú)占鎖

acquire獲取獨(dú)占鎖

  • 偽代碼實(shí)現(xiàn)
 while (!tryAcquire(arg)) {
    <em>enqueue thread if it is not already queued</em>;
    <em>possibly block current thread</em>;
 }
  • 代碼實(shí)現(xiàn)
    • 先嘗試獲取鎖嵌戈,獲取成功則成功
    • 嘗試失敗覆积,則把當(dāng)前線程包裝成為一個(gè)節(jié)點(diǎn),然后等待獲取的機(jī)會(huì)
public final void acquire(int arg) {
    if (!tryAcquire(arg) &&
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
        selfInterrupt();
}
  • NOTE這里有必要說(shuō)明一下熟呛,就是當(dāng)一個(gè)節(jié)點(diǎn)成為head節(jié)點(diǎn)的時(shí)候宽档,他不一定會(huì)是下一個(gè)獲取鎖的節(jié)點(diǎn),從上面代碼也可以看出來(lái)庵朝,所以獲取鎖的線程都會(huì)先嘗試獲取鎖一次吗冤,這樣有可能等待隊(duì)列的頭節(jié)點(diǎn)也可能獲取鎖失敗。

release釋放獨(dú)占鎖

  • 偽代碼實(shí)現(xiàn)
  if (tryRelease(arg))
     <em>unblock the first queued thread</em>;
  • 代碼實(shí)現(xiàn)
public final boolean release(int arg) {
    if (tryRelease(arg)) {
        Node h = head;
        if (h != null && h.waitStatus != 0)
            unparkSuccessor(h);
        return true;
    }
    return false;
}

共享鎖

acquireShared獲取共享鎖

  • 代碼實(shí)現(xiàn)
public final void acquireShared(int arg) {
    if (tryAcquireShared(arg) < 0)
        doAcquireShared(arg);
}

releaseShared釋放共享鎖

  • 代碼實(shí)現(xiàn)
public final boolean releaseShared(int arg) {
    if (tryReleaseShared(arg)) {
        doReleaseShared();
        return true;
    }
    return false;
}

FIFO隊(duì)列

隊(duì)列模型

這個(gè)在AQS的注釋說(shuō)明里邊九府,Doug Lea已經(jīng)說(shuō)的很明確了椎瘟,還做了圖解

  • 這個(gè)等待隊(duì)列是CLH(Craig, Landin, and Hagersten)隊(duì)列的一個(gè)變種,這種隊(duì)列常被用作自旋鎖(這個(gè)概念就不展開了)
  • 作用:用于阻塞同步器
  • 結(jié)構(gòu)
         +------+  prev +-----+       +-----+
 head    |      | <---- |     | <---- |     |  tail
         +------+       +-----+       +-----+
  • 入隊(duì):插入隊(duì)尾
  • 出隊(duì):直接設(shè)置head即可

節(jié)點(diǎn)

  • 節(jié)點(diǎn)其實(shí)是把想要獲取鎖的線程包裝了一番
//mode分exclusive和shared兩種模式
new Node(Thread.currentThread(), mode);
  • 節(jié)點(diǎn)狀態(tài)
/** waitStatus value to indicate thread has cancelled */
static final int CANCELLED =  1;
/** waitStatus value to indicate successor's thread needs unparking */
static final int SIGNAL    = -1;
/** waitStatus value to indicate thread is waiting on condition */
static final int CONDITION = -2;
/**
 * waitStatus value to indicate the next acquireShared should
 * unconditionally propagate. 
 * 這個(gè)狀態(tài)只在共享鎖的模式下有效侄旬,這個(gè)傳播的用處在哪兒呢肺蔚?
 * 舉例說(shuō)明:讀寫鎖,寫讀操作和寫寫操作互斥儡羔,讀讀之間不互斥宣羊;當(dāng)調(diào)用acquireShared獲取讀
 * 鎖時(shí),會(huì)檢查后續(xù)節(jié)點(diǎn)是否是獲取讀鎖汰蜘,如果是仇冯,則同樣釋放;
 */
static final int PROPAGATE = -3;

常見面試

  • 談一下AQS吧 @可以從定義入手鉴扫,然后講
    • 不同鎖狀態(tài)的更改的實(shí)現(xiàn)方式
    • FIFO隊(duì)列的實(shí)現(xiàn)方式
    • 核心技術(shù)CAS+volatile
  • CAS是什么赞枕?見上面的筆記
  • 為什么你說(shuō)AQS的底層是CAS+volatile?
    • 表示鎖狀態(tài)的變量state坪创,以及FIFO隊(duì)列的頭炕婶,尾,節(jié)點(diǎn)的狀態(tài)都是volatile修飾的
    • 在設(shè)置state莱预,隊(duì)列的頭柠掂,尾,狀態(tài)的時(shí)候都有用到CAS技術(shù)
  • JUC包里的同步組件主要實(shí)現(xiàn)了AQS的哪些主要方法 依沮?
    • tryAcquire, tryRelease
    • tryAcquireShared, tryReleaseShared
    • isHeldExclusively
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末涯贞,一起剝皮案震驚了整個(gè)濱河市枪狂,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌宋渔,老刑警劉巖州疾,帶你破解...
    沈念sama閱讀 212,542評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異皇拣,居然都是意外死亡严蓖,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門氧急,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)颗胡,“玉大人,你說(shuō)我怎么就攤上這事吩坝《疽蹋” “怎么了?”我有些...
    開封第一講書人閱讀 158,021評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵钉寝,是天一觀的道長(zhǎng)弧呐。 經(jīng)常有香客問(wèn)我,道長(zhǎng)瘩蚪,這世上最難降的妖魔是什么泉懦? 我笑而不...
    開封第一講書人閱讀 56,682評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮疹瘦,結(jié)果婚禮上崩哩,老公的妹妹穿的比我還像新娘。我一直安慰自己言沐,他們只是感情好邓嘹,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,792評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著险胰,像睡著了一般汹押。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上起便,一...
    開封第一講書人閱讀 49,985評(píng)論 1 291
  • 那天棚贾,我揣著相機(jī)與錄音,去河邊找鬼榆综。 笑死妙痹,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的鼻疮。 我是一名探鬼主播怯伊,決...
    沈念sama閱讀 39,107評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼判沟!你這毒婦竟也來(lái)了耿芹?” 一聲冷哼從身側(cè)響起崭篡,我...
    開封第一講書人閱讀 37,845評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎吧秕,沒想到半個(gè)月后琉闪,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,299評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡砸彬,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,612評(píng)論 2 327
  • 正文 我和宋清朗相戀三年塘偎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拿霉。...
    茶點(diǎn)故事閱讀 38,747評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖咱扣,靈堂內(nèi)的尸體忽然破棺而出绽淘,到底是詐尸還是另有隱情,我是刑警寧澤闹伪,帶...
    沈念sama閱讀 34,441評(píng)論 4 333
  • 正文 年R本政府宣布沪铭,位于F島的核電站,受9級(jí)特大地震影響偏瓤,放射性物質(zhì)發(fā)生泄漏杀怠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,072評(píng)論 3 317
  • 文/蒙蒙 一厅克、第九天 我趴在偏房一處隱蔽的房頂上張望赔退。 院中可真熱鬧,春花似錦证舟、人聲如沸硕旗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)漆枚。三九已至,卻和暖如春抵知,著一層夾襖步出監(jiān)牢的瞬間墙基,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工刷喜, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留残制,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,545評(píng)論 2 362
  • 正文 我出身青樓吱肌,卻偏偏與公主長(zhǎng)得像痘拆,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子氮墨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,658評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容