AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當(dāng)前位置:首頁 > 科技  > 軟件

被問到ReentrantLock你真的能答好嗎?

來源: 責(zé)編: 時(shí)間:2023-10-26 17:10:11 229觀看
導(dǎo)讀一、先了解一下我們知道實(shí)現(xiàn)一把鎖要有如下幾個(gè)邏輯:鎖的標(biāo)識(shí)線程搶鎖的邏輯線程掛起的邏輯線程存儲(chǔ)邏輯線程釋放鎖的邏輯線程喚醒的邏輯我們?cè)谥v解AQS的時(shí)候說過AQS基本負(fù)責(zé)了實(shí)現(xiàn)鎖的全部邏輯,唯獨(dú)線程搶鎖和線程釋放

一、先了解一下

我們知道實(shí)現(xiàn)一把鎖要有如下幾個(gè)邏輯:Zy628資訊網(wǎng)——每日最新資訊28at.com

  • 鎖的標(biāo)識(shí)
  • 線程搶鎖的邏輯
  • 線程掛起的邏輯
  • 線程存儲(chǔ)邏輯
  • 線程釋放鎖的邏輯
  • 線程喚醒的邏輯

我們?cè)谥v解AQS的時(shí)候說過AQS基本負(fù)責(zé)了實(shí)現(xiàn)鎖的全部邏輯,唯獨(dú)線程搶鎖和線程釋放鎖的邏輯是交給子類來實(shí)現(xiàn)了,而ReentrantLock作為最常用的獨(dú)占鎖,其內(nèi)部就是包含了AQS的子類實(shí)現(xiàn)了線程搶鎖和釋放鎖的邏輯。Zy628資訊網(wǎng)——每日最新資訊28at.com

Zy628資訊網(wǎng)——每日最新資訊28at.com

我們?cè)谑褂肦eentrantLock的時(shí)候一般只會(huì)使用如下方法:Zy628資訊網(wǎng)——每日最新資訊28at.com

 ReentrantLock lock=new ReentrantLock(); lock.lock(); lock.unlock(); lock.tryLock(); Condition condition=lock.newCondition(); condition.await(); condition.signal(); condition.signalAll();     

二、技術(shù)架構(gòu)

如果我們自己來實(shí)現(xiàn)一個(gè)鎖,那么如何設(shè)計(jì)呢?Zy628資訊網(wǎng)——每日最新資訊28at.com

根據(jù)AQS的邏輯,我們寫一個(gè)子類sync,這個(gè)類一定會(huì)調(diào)用父類的acquire方法進(jìn)行上鎖,同時(shí)重寫tryAcquire方法實(shí)現(xiàn)自己搶鎖邏輯,也一定會(huì)調(diào)用release方法進(jìn)行解鎖,同時(shí)重寫tryRelease方法實(shí)現(xiàn)釋放鎖邏輯。Zy628資訊網(wǎng)——每日最新資訊28at.com

Zy628資訊網(wǎng)——每日最新資訊28at.com

那么ReentrantLock是怎么實(shí)現(xiàn)的呢?Zy628資訊網(wǎng)——每日最新資訊28at.com

ReentrantLock的實(shí)現(xiàn)的類架構(gòu)如下,ReentrantLock對(duì)外提供作為一把鎖應(yīng)該具備的api,比如lock加鎖,unlock解鎖等等,而它內(nèi)部真正的實(shí)現(xiàn)是通過靜態(tài)內(nèi)部類sync實(shí)現(xiàn),sync是AQS的子類,是真正的鎖,因?yàn)檫@把鎖需要支持公平和非公平的特性,所以sync又有兩個(gè)子類FairSync和NonfairSync分別實(shí)現(xiàn)公平鎖和非公平鎖。Zy628資訊網(wǎng)——每日最新資訊28at.com

Zy628資訊網(wǎng)——每日最新資訊28at.com

因?yàn)槭欠窆秸f的是搶鎖的時(shí)候是否公平,那兩個(gè)子類就要在上鎖方法acquire的調(diào)用和搶鎖方法tryAcquire的重寫上做文章。Zy628資訊網(wǎng)——每日最新資訊28at.com

公平鎖做了什么文章?Zy628資訊網(wǎng)——每日最新資訊28at.com

 static final class FairSync extends Sync {          final void lock() {            acquire(1);        }        protected final boolean tryAcquire(int acquires) {            final Thread current = Thread.currentThread();            int c = getState();            if (c == 0) {                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;        }    }

公平鎖比較簡(jiǎn)單,直接調(diào)用了父級(jí)類AQS的acquire方法,因?yàn)锳QS的鎖默認(rèn)就是公平的排隊(duì)策略。Zy628資訊網(wǎng)——每日最新資訊28at.com

重寫tryAcquire方法的邏輯為:Zy628資訊網(wǎng)——每日最新資訊28at.com

  • 判斷當(dāng)前鎖是否被占用,即state是否為0
  • 如果當(dāng)前鎖沒有被占用,然后會(huì)判斷等待隊(duì)列中是否有線程在阻塞等待,如果有,那就終止搶鎖,如果沒有,就通過cas搶鎖,搶到鎖返回true,沒有搶到鎖返回false。
  • 如果當(dāng)前鎖已經(jīng)被占用,然后判斷占用鎖的線程是不是自己,如果是,就會(huì)將state加1,表示重入,返回true。如果不是自己那就是代表沒有搶到鎖,返回false。

公平就公平在老老實(shí)實(shí)排隊(duì)。Zy628資訊網(wǎng)——每日最新資訊28at.com

非公平鎖做了什么文章?Zy628資訊網(wǎng)——每日最新資訊28at.com

  static final class NonfairSync extends Sync {              final void lock() {            if (compareAndSetState(0, 1))                setExclusiveOwnerThread(Thread.currentThread());            else                acquire(1);        }        protected final boolean tryAcquire(int acquires) {            return nonfairTryAcquire(acquires);        }    }        //nonfairTryAcquire代碼在父類sync里面     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;        }

非公平鎖也很簡(jiǎn)單,沒有直接調(diào)用了父級(jí)類AQS的acquire方法,而是先通過cas搶鎖,它不管等待隊(duì)列中有沒有其他線程在排隊(duì),直接搶鎖,這就體現(xiàn)了不公平。Zy628資訊網(wǎng)——每日最新資訊28at.com

它重寫tryAcquire方法的邏輯為:Zy628資訊網(wǎng)——每日最新資訊28at.com

  • 判斷當(dāng)前鎖是否被占用,即state是否為0
  • 如果當(dāng)前鎖沒有被占用,就直接通過cas搶鎖(不管等待隊(duì)列中有沒有線程在排隊(duì)),搶到鎖返回true,沒有搶到鎖返回false。
  • 如果當(dāng)前鎖已經(jīng)被占用,然后判斷占用鎖的線程是不是自己,如果是,就會(huì)將state加1,表示重入,返回true。如果不是自己那就是代表沒有搶到鎖,返回false。

公平鎖和非公平分別重寫了tryAcquire方法,來滿足公平和非公平的特性。那么tryAcquire方法也是需要子類重寫的,因?yàn)樗褪欠窆綗o關(guān),因此tryAcquire方法被抽象到sync類中重寫。Zy628資訊網(wǎng)——每日最新資訊28at.com

sync類中protected final boolean tryRelease(int releases) {            int c = getState() - releases;            if (Thread.currentThread() != getExclusiveOwnerThread())                throw new IllegalMonitorStateException();            boolean free = false;            if (c == 0) {                free = true;                setExclusiveOwnerThread(null);            }            setState(c);            return free;        }

釋放鎖的邏輯如下:Zy628資訊網(wǎng)——每日最新資訊28at.com

  • 獲取state的值,然后減1
  • 如果state為0,代表鎖已經(jīng)釋放,清空aqs中的持有鎖的線程字段的值
  • 如果state不為0,說明當(dāng)前線程重入了,還需要再次釋放鎖
  • 將state寫回

釋放鎖往往和搶鎖邏輯是對(duì)應(yīng)的,每個(gè)子類搶鎖邏輯不同的話,釋放鎖的邏輯也會(huì)對(duì)應(yīng)不同。Zy628資訊網(wǎng)——每日最新資訊28at.com

三、具體實(shí)現(xiàn)

接下來我們通過ReentrantLock的使用看下它的源碼實(shí)現(xiàn):Zy628資訊網(wǎng)——每日最新資訊28at.com

class X {            private final ReentrantLock lock = new ReentrantLock();            Condition condition1=lock.newCondition();            Condition condition2=lock.newCondition();            public void m() {                lock.lock();                try {                    if(條件1){                        condition1.await();                    }                    if(條件2){                        condition2.await();                    }                } catch (InterruptedException e) {                } finally {                    condition1.signal();                    condition2.signal();                    lock.unlock();                }            }        }

1.先看這個(gè)方法:lock.lock()

ReentrantLock類public void lock() {        sync.lock();    }
  NonfairSync 類中  final void lock() {    if (compareAndSetState(0, 1))    setExclusiveOwnerThread(Thread.currentThread());    else      acquire(1);  }
  FairSync 類中  final void lock() {      acquire(1);  }     

公平鎖和非公平鎖中都實(shí)現(xiàn)了lock方法,公平鎖直接調(diào)用AQS的acquire,而非公平鎖先搶鎖,搶不到鎖再調(diào)用AQS的acquire方法進(jìn)行上鎖Zy628資訊網(wǎng)——每日最新資訊28at.com

進(jìn)入acquire方法后的邏輯我們就都知道了。Zy628資訊網(wǎng)——每日最新資訊28at.com

2.再看這個(gè)方法lock.unlock()

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

unlock方法內(nèi)直接調(diào)用了AQS的Release方法進(jìn)行解鎖的邏輯,進(jìn)入release方法后邏輯我們都已經(jīng)知道了,這里不再往下跟。Zy628資訊網(wǎng)——每日最新資訊28at.com

3.最后看這個(gè)方法lock.tryLock()

這個(gè)方法中直接調(diào)用了sync中的nonfairTryAcquire方法,這個(gè)就是非公平鎖實(shí)現(xiàn)的TryAcquire方法,只是名字改了而已。Zy628資訊網(wǎng)——每日最新資訊28at.com

tryLock方法的意思是嘗試搶鎖,是給程序員調(diào)用的嘗試搶鎖方法,如果搶鎖成功返回true,搶鎖失敗返回false,當(dāng)拿到搶鎖失敗的信號(hào)后,程序員可以做一些自己的策略。Zy628資訊網(wǎng)——每日最新資訊28at.com

如果沒有tryLock方法,而是直接調(diào)用lock方法,就會(huì)走到acquire方法中,Acquire方法中也會(huì)調(diào)用TryAcquire方法,只不過在這里如果獲取不到鎖就會(huì)入隊(duì)阻塞了,就沒有程序員參與的可能了。Zy628資訊網(wǎng)——每日最新資訊28at.com

4.lock.newCondition();

在AQS那篇我們說過Condition是AQS中的條件隊(duì)列,可以按條件將一批線程由不可喚醒變?yōu)榭蓡拘选?span style="display:none">Zy628資訊網(wǎng)——每日最新資訊28at.com

ReentrantLock類 public Condition newCondition() {        return sync.newCondition(); }
sync靜態(tài)內(nèi)部類final ConditionObject newCondition() {            return new ConditionObject();}

sync提供了創(chuàng)建Condition對(duì)象的方法,意味著ReentrantLock也擁有Condition的能力。Zy628資訊網(wǎng)——每日最新資訊28at.com

四、ReentrantLock和synchronized對(duì)比

我們下面說的ReentrantLock其實(shí)就是說AQS,因?yàn)樗耐綄?shí)現(xiàn)主要在AQS里面。Zy628資訊網(wǎng)——每日最新資訊28at.com

1.實(shí)現(xiàn)方面

  • ReentrantLock是jdk級(jí)別實(shí)現(xiàn)的,其源碼在jdk源碼中可以查看,沒有脫離java。
  • synchronized是jvm級(jí)別實(shí)現(xiàn)的,synchronized只是java端的一個(gè)關(guān)鍵字,具體邏輯實(shí)現(xiàn)都在jvm中。

2.性能方面

優(yōu)化前的synchronized性能很差,主要表現(xiàn)在兩個(gè)方面:Zy628資訊網(wǎng)——每日最新資訊28at.com

  • 因?yàn)榇蠖鄶?shù)情況下對(duì)于資源的爭(zhēng)奪并沒有那么激烈,甚至于某個(gè)時(shí)刻可能只有一個(gè)線程在工作,在這種沒有競(jìng)爭(zhēng)或者競(jìng)爭(zhēng)壓力很小的情況下,如果每個(gè)線程都要進(jìn)行用戶態(tài)到內(nèi)核態(tài)的切換其實(shí)是很耗時(shí)的。
  • jdk1.6對(duì)synchronized底層實(shí)現(xiàn)做了優(yōu)化,優(yōu)化后,在單線程以及并發(fā)不是很高的情況下通過無鎖偏向和自旋鎖的方式避免用戶態(tài)到內(nèi)核態(tài)的切換,因此性能提高了,優(yōu)化后的synchronized和ReentrantLock性能差不多了。

ReentrantLock是在jdk實(shí)現(xiàn)的,它申請(qǐng)互斥量就是對(duì)鎖標(biāo)識(shí)state的爭(zhēng)奪,它是通過cas方式實(shí)現(xiàn)。在java端實(shí)現(xiàn)。Zy628資訊網(wǎng)——每日最新資訊28at.com

對(duì)于爭(zhēng)奪不到資源的線程依然要阻塞掛起,但凡阻塞掛起都要依賴于操作系統(tǒng)底層,這一步的用戶態(tài)到內(nèi)核態(tài)的切換是避免不了的。Zy628資訊網(wǎng)——每日最新資訊28at.com

因此在單線程進(jìn)入代碼塊的時(shí)候,效率是很高的,因此我們說ReentrantLock性能高于原始的synchronized:Zy628資訊網(wǎng)——每日最新資訊28at.com

  • 申請(qǐng)互斥量:synchronized的鎖其實(shí)就是爭(zhēng)奪Monitor鎖的擁有權(quán),這個(gè)爭(zhēng)奪過程是通過操作系統(tǒng)底層的互斥原語Mutex實(shí)現(xiàn)的,這個(gè)過程會(huì)有用戶態(tài)到內(nèi)核態(tài)的切換。
  • 線程阻塞掛起:沒能搶到到Monitor鎖擁有權(quán)的線程要阻塞掛起,阻塞掛起這個(gè)動(dòng)作也是依靠操作系統(tǒng)實(shí)現(xiàn)的,這個(gè)過程也需要用戶態(tài)到內(nèi)核態(tài)的切換。

3.特性方面

兩個(gè)都是常用的典型的獨(dú)占鎖。Zy628資訊網(wǎng)——每日最新資訊28at.com

  • ReentrantLock可重入,可中斷,支持公平和非公平鎖,可嘗試獲取鎖,可以支持分組將線程由不可喚醒變?yōu)榭蓡拘选?/li>
  • synchronized可重入,不可中斷,非公平鎖,不可嘗試獲取鎖,只支持一個(gè)或者全部線程由不可喚醒到可喚醒。

4.使用方面

synchronized不需要手動(dòng)釋放鎖,ReentrantLock需要手動(dòng)釋放鎖,需要考慮異常對(duì)釋放鎖的影響避免異常導(dǎo)致線程一直持有鎖。Zy628資訊網(wǎng)——每日最新資訊28at.com

以下是兩個(gè)鎖的使用方式:Zy628資訊網(wǎng)——每日最新資訊28at.com

class X {            private final ReentrantLock lock = new ReentrantLock();            Condition condition1=lock.newCondition();            Condition condition2=lock.newCondition();            public void m() {                lock.lock();                try {                    if(1==2){                        condition1.await();                    }                    if(1==3){                        condition2.await();                    }                } catch (InterruptedException e) {                } finally {                    condition1.signal();                    condition2.signal();                    lock.unlock();                }            }        }
   class X {            private final testtest sync=new testtest();;            public void m() throws InterruptedException {                synchronized(sync){                    if(1==2){                        sync.wait();                    }                    sync.notify();                    sync.notifyAll();                }            }        }

對(duì)比代碼及特性說明:Zy628資訊網(wǎng)——每日最新資訊28at.com

  • 兩個(gè)鎖都是依賴一個(gè)對(duì)象:lock和sync
  • condition和wait方法具有同樣的效果,進(jìn)入condition和wait的線程將陷入等待(不可喚醒狀態(tài)),只有被分別調(diào)用signal和notify方法線程才會(huì)重新變?yōu)榭蓡拘褷顟B(tài),請(qǐng)注意是可喚醒,而不是被喚醒。
  • 可喚醒是說具備了競(jìng)爭(zhēng)資源的資格,資源空閑后,synchronized中會(huì)在可喚醒狀態(tài)的線程中隨機(jī)挑選一個(gè)線程去拿鎖,而ReentrantLock中不可喚醒的線程變?yōu)榭蓡拘褷顟B(tài),其實(shí)就是將條件隊(duì)列中的線程搬到等待隊(duì)列中排隊(duì),只有隊(duì)頭的才會(huì)去嘗試拿鎖。
  • ReentrantLock分批將線程由不可喚醒變?yōu)榭蓡拘岩苍谶@段代碼中體現(xiàn)了,代碼中按照不同的條件將線程放入不同的condition,每個(gè)condition就是一個(gè)組,釋放的時(shí)候也可以按照不同的條件進(jìn)行釋放。而synchronized中進(jìn)入wait的線程不能分組,釋放也只能隨機(jī)釋放一個(gè)或者全部釋放。

本文鏈接:http://www.tebozhan.com/showinfo-26-15183-0.html被問到ReentrantLock你真的能答好嗎?

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com

上一篇: 是時(shí)候放棄Dockerfile了,考慮上手Buildpack吧

下一篇: 掌握Go編程中的錯(cuò)誤處理和日志記錄

標(biāo)簽:
  • 熱門焦點(diǎn)
  • 一加Ace2 Pro官宣:普及16G內(nèi)存 引領(lǐng)24G

    一加官方今天繼續(xù)為本月發(fā)布的新機(jī)一加Ace2 Pro帶來預(yù)熱,公布了內(nèi)存方面的信息。“淘汰 8GB ,12GB 起步,16GB 普及,24GB 引領(lǐng),還有呢?#一加Ace2Pro#,2023 年 8 月,敬請(qǐng)期待。”同時(shí)
  • 盧偉冰長文解析K60至尊版 對(duì)Redmi有著里程碑式的意義

    在今天的Redmi后性能時(shí)代戰(zhàn)略發(fā)布會(huì)結(jié)束之后,Redmi總經(jīng)理盧偉冰又帶來了一篇長文,詳解了為什么 Redmi 要開啟后性能時(shí)代?為什么選擇和 MediaTek、Pixelworks 深度合作?以及后性
  • Redmi Buds 4開箱簡(jiǎn)評(píng):才199還有降噪 可以無腦入

    在上個(gè)月舉辦的Redmi Note11T Pro系列新機(jī)發(fā)布會(huì)上,除了兩款手機(jī)新品之外,Redmi還帶來了兩款TWS真無線藍(lán)牙耳機(jī)產(chǎn)品,Redmi Buds 4和Redmi Buds 4 Pro,此前我們?cè)赗edmi Note11T
  • 如何正確使用:Has和:Nth-Last-Child

    我們可以用CSS檢查,以了解一組元素的數(shù)量是否小于或等于一個(gè)數(shù)字。例如,一個(gè)擁有三個(gè)或更多子項(xiàng)的grid。你可能會(huì)想,為什么需要這樣做呢?在某些情況下,一個(gè)組件或一個(gè)布局可能會(huì)
  • 谷歌KDD'23工作:如何提升推薦系統(tǒng)Ranking模型訓(xùn)練穩(wěn)定性

    谷歌在KDD 2023發(fā)表了一篇工作,探索了推薦系統(tǒng)ranking模型的訓(xùn)練穩(wěn)定性問題,分析了造成訓(xùn)練穩(wěn)定性存在問題的潛在原因,以及現(xiàn)有的一些提升模型穩(wěn)定性方法的不足,并提出了一種新
  • 一文搞定Java NIO,以及各種奇葩流

    大家好,我是哪吒。很多朋友問我,如何才能學(xué)好IO流,對(duì)各種流的概念,云里霧里的,不求甚解。用到的時(shí)候,現(xiàn)百度,功能雖然實(shí)現(xiàn)了,但是為什么用這個(gè)?不知道。更別說效率問題了~下次再遇到,
  • 聯(lián)想小新Pad Pro 12.6將要推出,搭載高通驍龍 870 處理器

    聯(lián)想小新Pad Pro 12.6將于秋季新品會(huì)上推出,官方按照慣例直接在發(fā)布會(huì)前給出了機(jī)型的所有參數(shù)。聯(lián)想小新 Pad Pro 12.6 將搭載高通驍龍 870 處理器,重量為 5
  • 最薄的14英寸游戲筆記本電腦 Alienware X14已可以購買

    2022年1月份在國際消費(fèi)電子展(CES2022)上首次亮相的Alienware新品——Alienware X14現(xiàn)在已經(jīng)可以購買了,這款筆記本電腦被譽(yù)為世界上最薄的 14 英寸游戲筆
  • 三翼鳥智能家居亮相電博會(huì),讓用戶體驗(yàn)更真實(shí)

    2021電博會(huì)在青島國際會(huì)展中心開幕中,三翼鳥直接把“家”搬到了現(xiàn)場(chǎng),成為了展會(huì)的一大看點(diǎn)。這也是三翼鳥繼9月9日發(fā)布了行業(yè)首個(gè)一站式定制智慧家平臺(tái)后的
Top