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