并發(fā)編程-(6)-AQS原理波岛、一步一步圖解Exclusive模式獲得所&釋放鎖內(nèi)存變化茅坛、ReentrantLock:acquire & release 、喚醒節(jié)點(diǎn)為何要倒序遍歷同步隊(duì)列则拷?

死神--->一番隊(duì)隊(duì)長(zhǎng)山本元柳齋重國(guó)

目錄:

  • 1贡蓖、Lock介紹
  • 2、Lock的實(shí)現(xiàn)類ReentrantLock
  • 3煌茬、AQS簡(jiǎn)介
  • 4斥铺、ReentrantLock類體系
  • 5 、Lock使用
  • 6坛善、AQS原理:
    • 6.1晾蜘、AQS內(nèi)存模型
    • 6.2、AQS類體系
    • 6.3浑吟、AQS模板方法
    • 6.4笙纤、Node節(jié)點(diǎn)
    • 6.5、CHL同步隊(duì)列
    • 6.6组力、同步狀態(tài)獲仁∪荨(acquire)與釋放(release)
    • 6.7、線程阻塞與喚醒
  • 7燎字、AQS-產(chǎn)品之一ReentrantLock
    • 7.1腥椒、圖解:獲取鎖阿宅、釋放鎖、入同步隊(duì)列
    • 7.2笼蛛、公平鎖&非公平鎖
  • 8洒放、面試常見問題
    • 1、公平鎖(FairSync)和非公平鎖(NonfairSync)的區(qū)別滨砍?
    • 2往湿、ReentrantLock如何處理線程中斷的?
    • 3、未完待續(xù)~


1惋戏、Lock介紹

Lock 接口實(shí)現(xiàn)類提供了比使用 synchronized 方法和語(yǔ)句可獲得的更廣泛的鎖定操作领追。此實(shí)現(xiàn)允許更靈活的結(jié)構(gòu),可以具有差別很大的屬性响逢,可以支持多個(gè)相關(guān)的 Condition 對(duì)象(Condition實(shí)現(xiàn)類ConditonObject來實(shí)現(xiàn)線程的通知/與喚醒機(jī)制绒窑,關(guān)于Condition傳送門
)。

2舔亭、 Lock的實(shí)現(xiàn)類ReentrantLock

ReentrantLock是根據(jù)AQS實(shí)現(xiàn)的獨(dú)占鎖(exclusive)些膨。

3、 AQS簡(jiǎn)介

AQS全稱AbstractQueuedSynchronizer,是java并發(fā)包中的一個(gè)類钦铺,該類更像是一個(gè)框架(模板方法模式)订雾,提供了一些模板方法供子類實(shí)現(xiàn),從而實(shí)現(xiàn)了不同的同步器矛洞,如下圖所示葬燎。ReentrantLock,ReentrantReadWriteLock缚甩,CountDownLatch、ThreadPoolExecutor等 這些常見類都使用了AQS窑邦。

4擅威、 ReentrantLock類體系

ReentrantLock類體系結(jié)構(gòu)

5、Lock使用

eg:加鎖/解鎖偽代碼
Lock lock = new xxxLock();
try{
  // 加鎖
  lock.lock();
  balabala作相應(yīng)業(yè)務(wù)
} finally{
  // 解鎖
  lock.unlock();
}

6冈钦、AQS原理:

6.1郊丛、AQS內(nèi)存模型
AQS內(nèi)存模型
6.2、AQS類體系
AQS類體系結(jié)構(gòu)
6.3瞧筛、AQS模板方法
模板方法

抽象方法
6.4厉熟、Node節(jié)點(diǎn)
Node節(jié)點(diǎn)
6.5、CHL同步隊(duì)列
CHL同步隊(duì)列
6.6较幌、同步狀態(tài)獲茸嵘(acquire)與釋放(release)
獲取&釋放同步狀態(tài)
6.7、線程阻塞與喚醒
線程掛起&喚醒

7乍炉、AQS-產(chǎn)品之一ReentrantLock:

7.1绢片、圖解:獲取鎖滤馍、釋放鎖、入同步隊(duì)列
背景:Thread-A 底循、Thread-B巢株、Thread-C順序獲取鎖,模擬內(nèi)存中同步隊(duì)列變化熙涤。還要一種特殊情況:Thread-D獲取鎖失敗阁苞,同時(shí)入同步隊(duì)列失敗(最倒霉的線程D)祠挫。
Thread-A獲得重入鎖

Thread-B獲得鎖失敗那槽,入同步隊(duì)列

Thread-C入同步隊(duì)列
最倒霉的Thread-D加鎖失敗、入隊(duì)失敗g

如果node!=tail茸歧,不是尾節(jié)點(diǎn)倦炒,尾結(jié)點(diǎn)是Thread-X

走uparkSuccessor(node)

假設(shè)內(nèi)存中Thread-N中的 waitStatus=1
分析下第7-3步驟為何要倒序循環(huán)喚醒節(jié)點(diǎn)?
為何倒序喚醒節(jié)點(diǎn)软瞎?
7.2逢唤、公平鎖&非公平鎖

thread-6公平鎖入隊(duì)

thread-6非公平鎖入隊(duì)

8、面試常見問題:

  • 1涤浇、公平鎖(FairSync)和非公平鎖(NonfairSync)的區(qū)別鳖藕?
    鎖的公平性:獲取鎖順序而言的。
    共同點(diǎn):都是繼承自ReentrantLock內(nèi)部類Sync只锭。
    差異:
    • 公平鎖著恩,那么鎖的獲取順序就應(yīng)該符合請(qǐng)求的絕對(duì)時(shí)間順序,也就是 FIFO蜻展。
    • 非公平鎖喉誊,在獲取鎖的時(shí)候,會(huì)先通過 CAS 進(jìn)行搶占纵顾。
      另外公平鎖判斷條件多了 hasQueuedPredecessors()方法伍茄,也就是加入了[同步隊(duì)列中當(dāng)前節(jié)點(diǎn)是否有前驅(qū)節(jié)點(diǎn)]的判斷,如果該方法返回 true施逾,則表示有線程比當(dāng)前線程更早地請(qǐng)求獲取鎖敷矫, 因此需要等待前驅(qū)線程獲取并釋放鎖之后才能繼續(xù)獲取鎖。
      公平鎖加鎖方法:
// 公平鎖-獲取鎖的方法
     protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                // 同步隊(duì)列中當(dāng)前節(jié)點(diǎn)是否有前驅(qū)節(jié)點(diǎn)
                if (!hasQueuedPredecessors() &&
                    compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0)
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
    }

非公平鎖加鎖方法:

        final void lock() {
            // 嘗試CAS加鎖
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
                // 第一次嘗試失敗后汉额,走父類通用加鎖邏輯
                acquire(1);
        }
        // 父類模板方法回調(diào)tryAcquire方法
        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }

        final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }
  • 2曹仗、ReentrantLock如何處理線程中斷的?
    阻塞隊(duì)列使用的LockSupport.park();
private final boolean parkAndCheckInterrupt() {
        LockSupport.park(this);
        return Thread.interrupted();
    }

因?yàn)長(zhǎng)ockSupport.park(),無法響應(yīng)Thread.interrupt(); 所以當(dāng)unpark()后使用Thread.interrupted()來判斷線程是否有中斷過蠕搜。如果中斷過整個(gè)喚醒的線程在外層方法會(huì)繼續(xù)執(zhí)行一次中斷怎茫,詳情源碼如下:


image.png
image.png
static void selfInterrupt() {
        Thread.currentThread().interrupt();
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市妓灌,隨后出現(xiàn)的幾起案子遭居,更是在濱河造成了極大的恐慌啼器,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件俱萍,死亡現(xiàn)場(chǎng)離奇詭異端壳,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)枪蘑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門损谦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人岳颇,你說我怎么就攤上這事照捡。” “怎么了话侧?”我有些...
    開封第一講書人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵栗精,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我瞻鹏,道長(zhǎng)悲立,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任新博,我火速辦了婚禮薪夕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘赫悄。我一直安慰自己原献,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開白布埂淮。 她就那樣靜靜地躺著姑隅,像睡著了一般。 火紅的嫁衣襯著肌膚如雪倔撞。 梳的紋絲不亂的頭發(fā)上粤策,一...
    開封第一講書人閱讀 52,156評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音误窖,去河邊找鬼。 笑死秩贰,一個(gè)胖子當(dāng)著我的面吹牛霹俺,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播毒费,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼丙唧,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了觅玻?” 一聲冷哼從身側(cè)響起想际,我...
    開封第一講書人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤培漏,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后胡本,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體牌柄,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年侧甫,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了珊佣。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡披粟,死狀恐怖咒锻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情守屉,我是刑警寧澤惑艇,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布,位于F島的核電站拇泛,受9級(jí)特大地震影響滨巴,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜碰镜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一兢卵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧绪颖,春花似錦秽荤、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至牍氛,卻和暖如春晨继,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背搬俊。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來泰國(guó)打工紊扬, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人唉擂。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓餐屎,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親玩祟。 傳聞我的和親對(duì)象是個(gè)殘疾皇子腹缩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359