ReentrantLock源碼解析(解鎖)

源碼分析

16149389980022.jpg

1.unlock()方法實際是調(diào)用父類AQS的release()方法

public void unlock() {
        sync.release(1);
    }

2.release()方法首先又調(diào)用了tryRelease(1)方法怖亭,這個方法依舊由AQS的子類Sync類來實現(xiàn),見2.1分析

public final boolean release(int arg) {
        if (tryRelease(arg)) {
            Node h = head;
            if (h != null && h.waitStatus != 0)
                unparkSuccessor(h);
            return true;
        }
        return false;
    }
2.1 tryRelease()方法主要是對鎖狀態(tài)值進(jìn)行還原,并且釋放占有鎖的線程位迂,并將解鎖的結(jié)果返回
protected final boolean tryRelease(int releases) {
            //將鎖的狀態(tài)值-1
            int c = getState() - releases;
            //如果擁有鎖的線程不是現(xiàn)在的運行線程琅拌,則拋出異常拄轻,避免未lock情況下unlock
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            //鎖空閑標(biāo)識搅裙,默認(rèn)否
            boolean free = false;
            //如果鎖的狀態(tài)值恢復(fù)到0皱卓,則將鎖空閑標(biāo)識改為true总放,并將鎖的所屬線程設(shè)置為null
            if (c == 0) {
                free = true;
                setExclusiveOwnerThread(null);
            }
            //將鎖的狀態(tài)值同步到AQS里
            setState(c);
            return free;
        }

這里會有兩種情況
第一種情況不是重入鎖,釋放鎖后好爬,free狀態(tài)返回true局雄,再繼續(xù)后續(xù)的喚醒等待線程操作。
第二種情況如果是重入鎖釋放鎖存炮,則free狀態(tài)還是false炬搭,只是state的值遞減1,后面喚醒鎖的操作不會執(zhí)行

2.2 上面2.1分析的方法如果返回false則解鎖過程結(jié)束穆桂,如果返回true則繼續(xù)接第2步if方法體里代碼進(jìn)行喚醒等待線程
public final boolean release(int arg) {
        if (tryRelease(arg)) {
        //拿到頭節(jié)點
            Node h = head;
            
            if (h != null && h.waitStatus != 0)
                unparkSuccessor(h);
            return true;
        }
        return false;
    }

如果頭節(jié)點不是空宫盔,且頭節(jié)點的狀態(tài)不是0,執(zhí)行unparkSuccessor(h),入?yún)轭^節(jié)點享完,進(jìn)行喚醒操作;

private void unparkSuccessor(Node node) {
    
    //頭節(jié)點狀態(tài)
        int ws = node.waitStatus;
        //如果頭節(jié)點的狀態(tài)是-1將狀態(tài)改為0
        if (ws < 0)
            compareAndSetWaitStatus(node, ws, 0);
        //頭節(jié)點的后繼節(jié)點
        Node s = node.next;
        //如果后繼節(jié)點是null灼芭,或者狀態(tài)大于等于0,說明后繼節(jié)點取消了般又,為無效節(jié)點
        if (s == null || s.waitStatus > 0) {
            s = null;
            //從尾節(jié)點往前循環(huán)彼绷,找到符合狀態(tài)為小于等于0的節(jié)點,并賦給s
            for (Node t = tail; t != null && t != node; t = t.prev)
                if (t.waitStatus <= 0)
                    s = t;
        }
        //s不為null時茴迁,喚醒節(jié)點里的線程
        //喚醒的線程會從掛起的地方開始執(zhí)行寄悯,也就是繼上一篇文章《ReentrantLock源碼解析(加鎖)》第5.2.2節(jié)第5行繼續(xù)執(zhí)行。
        if (s != null)
            LockSupport.unpark(s.thread);
    }

這個方法做了幾步操作有健壯性的考慮堕义,
1.將頭節(jié)點的狀態(tài)改為0猜旬,避免重復(fù)循環(huán)
2.取到頭節(jié)點的后繼節(jié)點
3.校驗后繼節(jié)點的狀態(tài)是否可以被喚醒,如果后繼節(jié)點是空的倦卖,或者狀態(tài)大于0(線程被取消或者中斷)洒擦,則從尾節(jié)點開始循環(huán)找出最前面(FIFO隊列特點)可以被喚醒的線程。
4.喚醒上面2怕膛,3最終確定的等待線程

----------------- 文章如有問題熟嫩,請下方回復(fù)指出,感謝查閱?? -----------------

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末嘉竟,一起剝皮案震驚了整個濱河市邦危,隨后出現(xiàn)的幾起案子洋侨,更是在濱河造成了極大的恐慌舍扰,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件希坚,死亡現(xiàn)場離奇詭異边苹,居然都是意外死亡,警方通過查閱死者的電腦和手機裁僧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進(jìn)店門个束,熙熙樓的掌柜王于貴愁眉苦臉地迎上來慕购,“玉大人,你說我怎么就攤上這事茬底』Ρ” “怎么了?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵阱表,是天一觀的道長殿如。 經(jīng)常有香客問我,道長最爬,這世上最難降的妖魔是什么涉馁? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮爱致,結(jié)果婚禮上烤送,老公的妹妹穿的比我還像新娘。我一直安慰自己糠悯,他們只是感情好帮坚,可當(dāng)我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著互艾,像睡著了一般叶沛。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上忘朝,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天灰署,我揣著相機與錄音,去河邊找鬼局嘁。 笑死溉箕,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的悦昵。 我是一名探鬼主播肴茄,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼但指!你這毒婦竟也來了寡痰?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤棋凳,失蹤者是張志新(化名)和其女友劉穎拦坠,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體剩岳,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡贞滨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了拍棕。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片晓铆。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡勺良,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出骄噪,到底是詐尸還是另有隱情尚困,我是刑警寧澤,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布链蕊,位于F島的核電站尾组,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏示弓。R本人自食惡果不足惜讳侨,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望奏属。 院中可真熱鬧跨跨,春花似錦、人聲如沸囱皿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽嘱腥。三九已至耕渴,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間齿兔,已是汗流浹背橱脸。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留分苇,地道東北人添诉。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像医寿,于是被迫代替她去往敵國和親栏赴。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,465評論 2 348