摘要:二接口簡(jiǎn)介可以看做是類的方法的替代品,與配合使用。當(dāng)線程執(zhí)行對(duì)象的方法時(shí),當(dāng)前線程會(huì)立即釋放鎖,并進(jìn)入對(duì)象的等待區(qū),等待其它線程喚醒或中斷。
本文首發(fā)于一世流云的專欄:https://segmentfault.com/blog...
本系列文章中所說的juc-locks鎖框架就是指java.util.concurrent.locks包,該包提供了一系列基礎(chǔ)的鎖工具,用以對(duì)synchronizd、wait、notify等進(jìn)行補(bǔ)充、增強(qiáng)。
juc-locks鎖框架中一共就三個(gè)接口:Lock、Condition、ReadWriteLock,接下來對(duì)這些接口作介紹,更詳細(xì)的信息可以參考Oracle官方的文檔。
Lock接口可以視為synchronized的增強(qiáng)版,提供了更靈活的功能。該接口提供了限時(shí)鎖等待、鎖中斷、鎖嘗試等功能。
1.1 接口定義該接口的方法聲明如下:
需要注意lock()和lockInterruptibly()這兩個(gè)方法的區(qū)別:
lock()方法類似于使用synchronized關(guān)鍵字加鎖,如果鎖不可用,出于線程調(diào)度目的,將禁用當(dāng)前線程,并且在獲得鎖之前,該線程將一直處于休眠狀態(tài)。1.2 使用示例
lockInterruptibly()方法顧名思義,就是如果鎖不可用,那么當(dāng)前正在等待的線程是可以被中斷的,這比synchronized關(guān)鍵字更加靈活。
可以看到,Lock作為一種同步器,一般會(huì)用一個(gè)finally語句塊確保鎖最終會(huì)釋放。
Lock lock = ...; if (lock.tryLock()) { try { // manipulate protected state } finally { lock.unlock(); } } else { // perform alternative actions }二、Condition接口簡(jiǎn)介
Condition可以看做是Obejct類的wait()、notify()、notifyAll()方法的替代品,與Lock配合使用。
當(dāng)線程執(zhí)行condition對(duì)象的await方法時(shí),當(dāng)前線程會(huì)立即釋放鎖,并進(jìn)入對(duì)象的等待區(qū),等待其它線程喚醒或中斷。
JUC在實(shí)現(xiàn)Conditon對(duì)象時(shí),其實(shí)是通過實(shí)現(xiàn)AQS框架,來實(shí)現(xiàn)了一個(gè)Condition等待隊(duì)列,這個(gè)在后面講AQS框架時(shí)會(huì)詳細(xì)介紹,目前只要了解Condition如何使用即可。2.1 接口定義 2.2 使用示例
Oracle官方文檔中給出了一個(gè)緩沖隊(duì)列的示例:
假定有一個(gè)緩沖隊(duì)列,支持 put 和 take 方法。如果試圖在空隊(duì)列中執(zhí)行 take 操作,則線程將一直阻塞,直到隊(duì)列中有可用元素;如果試圖在滿隊(duì)列上執(zhí)行 put 操作,則線程也將一直阻塞,直到隊(duì)列不滿。
class BoundedBuffer { final Lock lock = new ReentrantLock(); final Condition notFull = lock.newCondition(); final Condition notEmpty = lock.newCondition(); ? final Object[] items = new Object[100]; int putptr, takeptr, count; ? public void put(Object x) throws InterruptedException { lock.lock(); try { while (count == items.length) //防止虛假喚醒,Condition的await調(diào)用一般會(huì)放在一個(gè)循環(huán)判斷中 notFull.await(); items[putptr] = x; if (++putptr == items.length) putptr = 0; ++count; notEmpty.signal(); } finally { lock.unlock(); } } ? public Object take() throws InterruptedException { lock.lock(); try { while (count == 0) notEmpty.await(); Object x = items[takeptr]; if (++takeptr == items.length) takeptr = 0; --count; notFull.signal(); return x; } finally { lock.unlock(); } } }
等待 Condition 時(shí),為了防止發(fā)生“虛假喚醒”, Condition 一般都是在一個(gè)循環(huán)中被等待,并測(cè)試正被等待的狀態(tài)聲明,如上述代碼注釋部分。三、ReadWriteLock接口簡(jiǎn)介
雖然上面這個(gè)示例程序即使不用while,改用if判斷也不會(huì)出現(xiàn)問題,但是最佳實(shí)踐還是做while循環(huán)判斷——Guarded Suspension模式,以防遺漏情況。
ReadWriteLock接口是一個(gè)多帶帶的接口(未繼承Lock接口),該接口提供了獲取讀鎖和寫鎖的方法。
所謂讀寫鎖,是一對(duì)相關(guān)的鎖——讀鎖和寫鎖,讀鎖用于只讀操作,寫鎖用于寫入操作。讀鎖可以由多個(gè)線程同時(shí)保持,而寫鎖是獨(dú)占的,只能由一個(gè)線程獲取。3.1 接口定義 3.2 使用注意
讀寫鎖的阻塞情況如下圖:
舉個(gè)例子,假設(shè)我有一份共享數(shù)據(jù)——訂單金額,大多數(shù)情況下,線程只會(huì)進(jìn)行高頻的數(shù)據(jù)訪問(讀取訂單金額),數(shù)據(jù)修改(修改訂單金額)的頻率較低。
那么一般情況下,如果采用互斥鎖,讀/寫和讀/讀都是互斥的,性能顯然不如采用讀寫鎖。
另外,由于讀寫鎖本身的實(shí)現(xiàn)就遠(yuǎn)比獨(dú)占鎖復(fù)雜,因此,讀寫鎖比較適用于以下情形:
高頻次的讀操作,相對(duì)較低頻次的寫操作;
讀操作所用時(shí)間不會(huì)太短。(否則讀寫鎖本身的復(fù)雜實(shí)現(xiàn)所帶來的開銷會(huì)成為主要消耗成本)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/71528.html
摘要:關(guān)于接口的介紹,可以參見多線程進(jìn)階二鎖框架接口。最終線程釋放了鎖,并進(jìn)入阻塞狀態(tài)。當(dāng)線程被通知喚醒時(shí),則是將條件隊(duì)列中的結(jié)點(diǎn)轉(zhuǎn)換成等待隊(duì)列中的結(jié)點(diǎn),之后的處理就和獨(dú)占功能完全一樣。 showImg(https://segmentfault.com/img/remote/1460000016012490); 本文首發(fā)于一世流云的專欄:https://segmentfault.com/bl...
摘要:公平策略在多個(gè)線程爭(zhēng)用鎖的情況下,公平策略傾向于將訪問權(quán)授予等待時(shí)間最長(zhǎng)的線程。使用方式的典型調(diào)用方式如下二類原理的源碼非常簡(jiǎn)單,它通過內(nèi)部類實(shí)現(xiàn)了框架,接口的實(shí)現(xiàn)僅僅是對(duì)的的簡(jiǎn)單封裝,參見原理多線程進(jìn)階七鎖框架獨(dú)占功能剖析 showImg(https://segmentfault.com/img/remote/1460000016012582); 本文首發(fā)于一世流云的專欄:https...
摘要:整個(gè)包,按照功能可以大致劃分如下鎖框架原子類框架同步器框架集合框架執(zhí)行器框架本系列將按上述順序分析,分析所基于的源碼為。后,根據(jù)一系列常見的多線程設(shè)計(jì)模式,設(shè)計(jì)了并發(fā)包,其中包下提供了一系列基礎(chǔ)的鎖工具,用以對(duì)等進(jìn)行補(bǔ)充增強(qiáng)。 showImg(https://segmentfault.com/img/remote/1460000016012623); 本文首發(fā)于一世流云專欄:https...
摘要:我們知道,的作用其實(shí)是對(duì)類的和的增強(qiáng),是為了讓線程在指定對(duì)象上等待,是一種線程之間進(jìn)行協(xié)調(diào)的工具。當(dāng)線程調(diào)用對(duì)象的方法時(shí),必須拿到和這個(gè)對(duì)象關(guān)聯(lián)的鎖。 showImg(https://segmentfault.com/img/remote/1460000016012566); 本文首發(fā)于一世流云的專欄:https://segmentfault.com/blog... 一、Reentr...
摘要:關(guān)于,最后有兩點(diǎn)規(guī)律需要注意當(dāng)?shù)牡却?duì)列隊(duì)首結(jié)點(diǎn)是共享結(jié)點(diǎn),說明當(dāng)前寫鎖被占用,當(dāng)寫鎖釋放時(shí),會(huì)以傳播的方式喚醒頭結(jié)點(diǎn)之后緊鄰的各個(gè)共享結(jié)點(diǎn)。當(dāng)?shù)牡却?duì)列隊(duì)首結(jié)點(diǎn)是獨(dú)占結(jié)點(diǎn),說明當(dāng)前讀鎖被使用,當(dāng)讀鎖釋放歸零后,會(huì)喚醒隊(duì)首的獨(dú)占結(jié)點(diǎn)。 showImg(https://segmentfault.com/img/remote/1460000016012293); 本文首發(fā)于一世流云的專欄:...
閱讀 943·2021-10-18 13:32
閱讀 3580·2021-09-30 09:47
閱讀 2189·2021-09-23 11:21
閱讀 1944·2021-09-09 09:34
閱讀 3532·2019-08-30 15:43
閱讀 1550·2019-08-30 11:07
閱讀 1099·2019-08-29 16:14
閱讀 756·2019-08-29 11:06