免费爱碰视频在线观看,九九精品国产屋,欧美亚洲尤物久久精品,1024在线观看视频亚洲

      面試官:有了解過(guò)ReentrantLock的底層實(shí)現(xiàn)嗎?說(shuō)說(shuō)看

      我們可以了解到它是一個(gè)可重入鎖,下面我們就一起看一下它的底層實(shí)現(xiàn)~

      構(gòu)造函數(shù)

      我們?cè)谑褂玫臅r(shí)候,都是先new它,所以我們先看下它的構(gòu)造函數(shù),它主要有兩個(gè):

      public ReentrantLock() { sync = new NonfairSync();}public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync();}

      從字面上看,它們之間的不同點(diǎn)在于fair,翻譯過(guò)來(lái)就是公平的意思,大體可以猜到它是用來(lái)構(gòu)建公平鎖和非公平鎖,在繼續(xù)往下看源碼之前,先給大家科普一下這兩種鎖。

      公平鎖 & 非公平鎖

      • 公平鎖 多個(gè)線程按照申請(qǐng)鎖的順序去獲得鎖,線程會(huì)直接進(jìn)入隊(duì)列去排隊(duì),永遠(yuǎn)都是隊(duì)列的第一位才能得到鎖。(例如銀行辦業(yè)務(wù)取號(hào))

      這種鎖的優(yōu)點(diǎn)很明顯,每個(gè)線程都能夠獲取資源,缺點(diǎn)也很明顯,如果某個(gè)線程阻塞了,其它線程也會(huì)阻塞,然而cpu喚醒開銷很大,之前也給大家講過(guò)

      • 非公平鎖 多個(gè)線程都去嘗試獲取鎖,獲取不到就進(jìn)入等待隊(duì)列,cpu也不用去喚醒

      優(yōu)缺點(diǎn)正好和上邊相反,優(yōu)點(diǎn)減少開銷,缺點(diǎn)也很明顯,可能會(huì)導(dǎo)致一直獲取不到鎖或長(zhǎng)時(shí)間獲取不到鎖

      好,有了基本概念之后,我們繼續(xù)往下看

      NonfairSync

      首先,我們看下非公平鎖,默認(rèn)情況下,我們申請(qǐng)的都是非公平鎖,也就是new ReentrantLock(),我們接著看源碼

      static final class NonfairSync extends Sync { private static final long serialVersionUID = 7316153563782823691L; /** * Performs lock. Try immediate barge, backing up to normal * acquire on failure. */ final void lock() { if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else acquire(1); } protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); }}

      它繼承了Sync,Sync是一個(gè)內(nèi)容靜態(tài)抽象類:

      abstract static class Sync extends AbstractQueuedSynchronizer {…}

      分為公平和非公平,使用AQS狀態(tài)來(lái)表示持鎖的次數(shù),在構(gòu)造函數(shù)初始化的時(shí)候都有sync = …,我們接著看NonfairSync。在使用的時(shí)候,我們調(diào)用了lock.lock()方法,它是ReentrantLock的一個(gè)實(shí)例方法

      // 獲取鎖 public void lock() { sync.lock(); }

      實(shí)際上內(nèi)部還是調(diào)了sync的內(nèi)部方法,因?yàn)槲覀兩暾?qǐng)的是非公平鎖,所以我們看NonfairSync下的lock實(shí)現(xiàn):

      final void lock() { if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else acquire(1);}

      compareAndSetState這個(gè)方法,是AQS的內(nèi)部方法,意思是如果當(dāng)前狀態(tài)值等于預(yù)期值,則自動(dòng)將同步狀態(tài)設(shè)置為給定的更新值。此操作具有volatile讀寫的內(nèi)存語(yǔ)義。

      protected final boolean compareAndSetState(int expect, int update) { // See below for intrinsics setup to support this return unsafe.compareAndSwapInt(this, stateOffset, expect, update);}

      可以看到執(zhí)行l(wèi)ock方法,會(huì)通過(guò)AQS機(jī)制計(jì)數(shù),setExclusiveOwnerThread設(shè)置線程獨(dú)占訪問(wèn)權(quán)限,它是AbstractOwnableSynchronizer的一個(gè)內(nèi)部方法,子類通過(guò)使用它來(lái)管理線程獨(dú)占

      public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable {}

      可以看到它是繼承了AbstractOwnableSynchronizer。下面接著看,我們說(shuō)如果實(shí)際值等于期望值會(huì)執(zhí)行上邊的方法,不期望的時(shí)候會(huì)執(zhí)行acquire(1)

      public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt();}

      這個(gè)方法以獨(dú)占模式獲取,忽略中斷,它會(huì)嘗試調(diào)用tryAcquire,成功會(huì)返回,不成功進(jìn)入線程排隊(duì),可以重復(fù)阻塞和解除阻塞。看下AQS 內(nèi)部的這個(gè)方法

      protected boolean tryAcquire(int arg) { throw new UnsupportedOperationException();}

      我們可以看到實(shí)現(xiàn)肯定不在這,它的具體實(shí)現(xiàn)在NonfairSync

      protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); }

      可以看到它調(diào)用了,nonfairTryAcquire方法,這個(gè)方法是不公平的tryLock,具體實(shí)現(xiàn)在Sync內(nèi)部,這里我們要重點(diǎn)關(guān)注一下

      final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); // 返回同步狀態(tài)值,它是AQS內(nèi)部的一個(gè)方法 // private volatile int state; // protected final int getState() { // return state; // } int c = getState(); if (c == 0) { // 為0就比較一下,如果與期望值相同就設(shè)置為獨(dú)占線程,說(shuō)明鎖已經(jīng)拿到了 if (compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } // 否則 判斷如果當(dāng)前線程已經(jīng)是被設(shè)置獨(dú)占線程了 else if (current == getExclusiveOwnerThread()) { // 設(shè)置當(dāng)前線程狀態(tài)值 + 1 并返回成功 int nextc = c + acquires; if (nextc < 0) // overflow throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } // 否則返回失敗 沒拿到鎖 return false;}

      好,我們?cè)倩剡^(guò)頭看下 acquire

      public final void acquire(int arg) { // 如果當(dāng)前線程沒有獲取到鎖 并且 在隊(duì)列中的線程嘗試不斷拿鎖如果被打斷了會(huì)返回true, 就會(huì)調(diào)用 selfInterrupt if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); }

      selfInterrupt很好理解,線程中斷

      static void selfInterrupt() { Thread.currentThread().interrupt(); }

      其實(shí)我們關(guān)注的重點(diǎn)是這個(gè)方法acquireQueued,首先關(guān)注一下入?yún)?它內(nèi)部傳入了一個(gè)addWaiter,最后它回NODE節(jié)點(diǎn)

      private Node addWaiter(Node mode) { // mode 沒啥好說(shuō)的就是一個(gè)標(biāo)記,用于標(biāo)記獨(dú)占模式 static final Node EXCLUSIVE = null; Node node = new Node(Thread.currentThread(), mode); // Try the fast path of enq; backup to full enq on failure Node pred = tail; if (pred != null) { node.prev = pred; if (compareAndSetTail(pred, node)) { pred.next = node; return node; } } enq(node); return node; }

      我們可以大體從猜到,Node是一個(gè)等待隊(duì)列的節(jié)點(diǎn)類,是一個(gè)鏈表結(jié)構(gòu),之前我們講FutureTask源碼的時(shí)候也遇到過(guò)這種結(jié)構(gòu),它通常用于自旋鎖,在這個(gè)地方,它是用于阻塞同步器

      +——+ prev +—–+ +—–+head | | <—- | | <—- | | tail +——+ +—–+ +—–+

      好,下面我們關(guān)注一下 acquireQueued

      final boolean acquireQueued(final Node node, int arg) { boolean failed = true; try { // 默認(rèn)是 false boolean interrupted = false; // 進(jìn)入阻塞循環(huán)遍歷 線程隊(duì)列 for (;;) { // 返回前一個(gè)節(jié)點(diǎn) final Node p = node.predecessor(); // 判斷如果前一個(gè)節(jié)點(diǎn)是頭部節(jié)點(diǎn),并且拿到鎖了,就會(huì)設(shè)置當(dāng)前節(jié)點(diǎn)為頭部節(jié)點(diǎn) if (p == head && tryAcquire(arg)) { setHead(node); // 這里可以看到注釋 help gc , p.next = null; // help GC failed = false; return interrupted; } // 檢查并更新未能獲取的節(jié)點(diǎn)的狀態(tài)。如果線程應(yīng)該阻塞,則返回 true 并且線程中斷了 if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) interrupted = true; } } finally { // 如果失敗 取消正在嘗試獲取的節(jié)點(diǎn) if (failed) cancelAcquire(node); }}

      從上面的源碼來(lái)看,在體會(huì)一下上面講的非公平鎖的概念,是不是更好理解一些,然后就是釋放鎖unlock,這個(gè)方法我們可以看到是ReentrantLock下的一個(gè)實(shí)例方法,所以公平鎖的釋放鎖也是調(diào)的這個(gè)方法,其實(shí)最終可以猜到調(diào)用的還是sync的方法

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

      Sync繼承AQS,release是AQS的內(nèi)部方法

      public final boolean release(int arg) { // 嘗試釋放鎖 tryRelease 在Sync內(nèi)部 if (tryRelease(arg)) { Node h = head; // 如果節(jié)點(diǎn)存在 并且狀態(tài)值不為0 if (h != null && h.waitStatus != 0) // 喚醒下個(gè)節(jié)點(diǎn) unparkSuccessor(h); return true; } return false; }private void unparkSuccessor(Node node) { int ws = node.waitStatus; if (ws 0) { s = null; for (Node t = tail; t != null && t != node; t = t.prev) if (t.waitStatus <= 0) s = t; } if (s != null) // 可以看到調(diào)用了 LockSupport來(lái)喚醒 LockSupport.unpark(s.thread); }

      我們?cè)倏聪聇ryRelease, 同樣這個(gè)實(shí)現(xiàn)在Sync內(nèi)

      protected final boolean tryRelease(int releases) { // 同樣釋放鎖的時(shí)候 依然使用 AQS計(jì)數(shù) int c = getState() – releases; // 判斷當(dāng)前線程是否是獨(dú)占線程,不是拋出異常 if (Thread.currentThread() != getExclusiveOwnerThread()) throw new IllegalMonitorStateException(); boolean free = false; // 如果是0 表示是釋放成功 if (c == 0) { free = true; // 并且把獨(dú)占線程設(shè)為null setExclusiveOwnerThread(null); } // 更新狀態(tài)值 setState(c); return free; }

      FairSync

      公平鎖FairSync的區(qū)別在于,它的獲取鎖的實(shí)現(xiàn)在它的內(nèi)部,Sync默認(rèn)內(nèi)部實(shí)現(xiàn)了非公平鎖

      static final class FairSync extends Sync { private static final long serialVersionUID = -3000897897090466540L; // 這個(gè)方法最終調(diào)用 tryAcquire final void lock() { acquire(1); } // 公平鎖的實(shí)現(xiàn) protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); // 這邊和非公平鎖的實(shí)現(xiàn)有些相似 同樣判斷狀態(tài) if (c == 0) { // 判斷排隊(duì)隊(duì)列是否存在, 不存在并且比較期望值 if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) { // 設(shè)置獨(dú)占線程 并返回成功 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; } }

      它的實(shí)現(xiàn)比較簡(jiǎn)單,通過(guò)實(shí)現(xiàn)可以發(fā)現(xiàn),它按照申請(qǐng)鎖的順序來(lái)獲取鎖,排第一的先拿到鎖,在結(jié)合上面的概念理解一下,就很好理解了.

      釋放鎖unlock,上面我們已經(jīng)講過(guò)了~

      結(jié)束語(yǔ)

      本節(jié)內(nèi)容可能有點(diǎn)多,主要是看源碼,可以打斷點(diǎn)自己調(diào)一下, 舉一反三,通過(guò)源碼去理解一下什么是公平鎖和非公平鎖, ReentrantLock可重入鎖體驗(yàn)在哪里。

      鄭重聲明:本文內(nèi)容及圖片均整理自互聯(lián)網(wǎng),不代表本站立場(chǎng),版權(quán)歸原作者所有,如有侵權(quán)請(qǐng)聯(lián)系管理員(admin#wlmqw.com)刪除。
      (0)
      用戶投稿
      上一篇 2022年6月19日 15:13
      下一篇 2022年6月19日 15:13

      相關(guān)推薦

      • 《鬼谷八荒》蜃靈珠怎么獲得?登仙境蜃靈珠獲得方法

        鬼谷八荒羽化登仙版本已經(jīng)正式更新,想必不少玩家在忙著突破最后的兩個(gè)階段,在登仙境中需要用到蜃靈珠,有些玩家不知道怎么獲取,這里給大家?guī)?lái)了鬼谷八荒登仙境蜃靈珠獲得方法,一起來(lái)看下具…

        2022年8月13日
      • 換手機(jī)屏感悟

        手機(jī)用了兩三年,手機(jī)膜有點(diǎn)損傷但不影響使用,今天遇到換模的換了,突然換了一個(gè)手機(jī)一樣,屏幕清晰度直線提升到剛買手機(jī)時(shí)候的狀態(tài),靈敏度也提高了。 聯(lián)想到人生中很多不開心不快樂,可能不…

        2022年6月14日
      • 一文梳理HTTP、TCP、Socket和WebSocket的區(qū)別和聯(lián)系

        一、OSI 網(wǎng)絡(luò)七層模型 第一層:應(yīng)用層,定義了用于在網(wǎng)絡(luò)中進(jìn)行通信和傳輸數(shù)據(jù)的接口;(Http協(xié)議位于該層) 第二層:表示層,定義不同系統(tǒng)中數(shù)據(jù)的傳輸格式,編碼和解碼規(guī)范等; 第…

        2022年7月19日
      • 手機(jī)管家沒用,手機(jī)深度清理垃圾的方法,趕緊收藏

        如果你的手機(jī)經(jīng)常提示內(nèi)存不足,或者看著自己手機(jī)的可用空間越來(lái)越少,很鬧心,刪照片和視頻都沒用,清理不出來(lái)多少空間,手機(jī)該卡還是卡。刪除照片和視頻只是刪除表面垃圾,并沒有做到徹底刪除…

        2022年6月19日
      • 成年人的真實(shí)現(xiàn)狀:白天假裝快樂,夜晚倍感“孤獨(dú)”

        孤獨(dú)是一種情緒狀態(tài),更是自我意識(shí)的失調(diào)。 當(dāng)我們感受到孤獨(dú)時(shí),說(shuō)明我們的潛意識(shí)已經(jīng)在孤獨(dú)的泥濘中掙扎了許久,但最終還是陷入深深的孤獨(dú)狀態(tài)中。 這樣的孤獨(dú),不僅是成長(zhǎng)性的孤獨(dú),更是情…

        2022年8月23日
      • 挑戰(zhàn)全網(wǎng)最爛的鼠標(biāo)

        我旅行的時(shí)間很長(zhǎng),旅途也是很長(zhǎng)的——泰戈?duì)?直擊心靈深處 身份信息顯示,這是賽睿sensei RAW 因?yàn)樽罱酝亮耍孕枰谕?,所以得到了這貨,經(jīng)典的賽睿SENSEI RAW鼠…

        2022年8月21日
      • 銀行卡為什么顯示卡狀態(tài)異常 有這些可能性

        不管銀行卡還是信用卡,在使用的過(guò)程中總會(huì)出現(xiàn)不同的問(wèn)題,其中卡片狀態(tài)異常是不少卡友反映的,那么銀行卡為什么顯示卡狀態(tài)異常呢,下面來(lái)看答案。 1、銀行卡過(guò)期,過(guò)期之后銀行會(huì)限制銀行卡…

        2022年8月24日
      • 梅西、內(nèi)馬爾和姆巴佩的新教練,能否拯救大巴黎?

        前不久,大巴黎終于官宣了新任主帥加爾杰的上任,很早以前我就喜歡這么一位有能力的主教練,不應(yīng)該被埋沒,他應(yīng)該得到一次執(zhí)教豪門的機(jī)會(huì),哪怕撞得頭破血流,我依然認(rèn)為他值得這一次嘗試,如今…

        2022年7月20日
      • 如何看待體罰學(xué)生的問(wèn)題?

        張清林的學(xué)生成績(jī)上不去,假如校長(zhǎng)用他體罰學(xué)生的方法體罰他,你認(rèn)為體罰學(xué)生對(duì)嗎? 頭條最近不斷出現(xiàn)些,無(wú)聊的,無(wú)中生有的問(wèn)題,干擾和牽制人們?yōu)檎x發(fā)生的精力,已經(jīng)極大的防礙了宣正能量…

        2022年4月13日
      • LeCun用62頁(yè)論文公布未來(lái)十年研究計(jì)劃:AI自主智能

        豐色 發(fā)自 凹非寺 量子位 | 公眾號(hào) QbitAI 這段時(shí)間,關(guān)于“AI未來(lái)往哪走的”討論,可以說(shuō)是越來(lái)越激烈了。 先是Meta被曝AI相關(guān)部門大重組,又有谷歌AI是否具備人格大…

        2022年6月30日

      聯(lián)系我們

      聯(lián)系郵箱:admin#wlmqw.com
      工作時(shí)間:周一至周五,10:30-18:30,節(jié)假日休息