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