日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

多线程—Lock、Condition、ReentrantLock、ReentrantReadWriteLock

發(fā)布時間:2023/12/18 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 多线程—Lock、Condition、ReentrantLock、ReentrantReadWriteLock 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Lock接口

public interface Lock { //下面4個方法都是獲得鎖void lock(); void lockInterruptibly() throws InterruptedException; // 如果當前線程未被中斷,則獲取鎖,可以響應中斷 boolean tryLock(); //如果獲取到鎖返回true,否則falseboolean tryLock(long var1, TimeUnit var3) throws InterruptedException; //如果獲取不到鎖,就等待一段時間,超時返回false。 //解除鎖,在finally里調(diào)用void unlock(); //返回Condition實例Condition newCondition(); }

對于Lock接口方法的實現(xiàn),大多都是調(diào)用AQS的方法來實現(xiàn)。實現(xiàn)Lock接口的類含有繼承了AQS一個內(nèi)部類(例如ReentrantLock的Sync內(nèi)部類),從而調(diào)用內(nèi)部類的繼承自AQS的方法或者重寫的方法來實現(xiàn)Lock接口的方法。

Lock接口最后還有一個返回Condition實例的方法。Condition是和Lock配合使用的。

在一個AQS同步器中,可以定義多個Condition,每一個Condition是一條FIFO隊列。只需要多次lock.newCondition(),每次都會返回一個新的ConditionObject對象。在ConditionObject中,通過一個條件隊列來維護等待的線程,這個隊列跟AQS的隊列不是同一條隊列,一個同步器中可以有多個條件隊列。

Condition接口

public interface Condition {// 當前線程進入等待狀態(tài)直到被通知(signal)或被中斷void await() throws InterruptedException;// 不響應中斷等待,直到被通知(signal)void awaitUninterruptibly();// 等待指定時長直到被通知或中斷或超時。long awaitNanos(long nanosTimeout) throws InterruptedException;// 等待指定時長直到被通知或中斷或超時。boolean await(long time, TimeUnit unit) throws InterruptedException;// 當前線程進入等待狀態(tài)直到被通知、中斷或者到某個時間。如果沒有到指定事件就被通知,方法返回true,否則false。 boolean awaitUntil(Date deadline) throws InterruptedException;// 喚醒一個等待在Condition上的線程,該線程從等待方法返回前必須獲得與Condition相關(guān)聯(lián)的鎖 void signal();// 喚醒所有等待在Condition上的線程,該線程從等待方法返回前必須獲得與Condition相關(guān)聯(lián)的鎖 void signalAll(); }

ConditionObject

ConditionObject是AQS中的內(nèi)部類,提供了條件鎖的同步實現(xiàn),實現(xiàn)了Condition接口,并且實現(xiàn)了其中的await(),signal(),signalALL()等方法。因為Condition的操作需要獲取相關(guān)聯(lián)的鎖,所以作為同步器的內(nèi)部類也較為合理。每個Condition對象都包含著一個FIFO等待隊列,該隊列是Condition對象實現(xiàn)等待/通知功能的關(guān)鍵。

當線程獲取到鎖之后,Condition對象調(diào)用await相關(guān)的方法:

public final void await() throws InterruptedException {if (Thread.interrupted())throw new InterruptedException();// 添加當前線程到條件隊列Node node = addConditionWaiter();// 釋放已經(jīng)獲取的鎖資源,并返回釋放前的同步狀態(tài)int savedState = fullyRelease(node);int interruptMode = 0;// 如果當前節(jié)點不在同步隊列中,線程進入阻塞狀態(tài),等待被喚醒while (!isOnSyncQueue(node)) {LockSupport.park(this);if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)break;}if (acquireQueued(node, savedState) && interruptMode != THROW_IE)interruptMode = REINTERRUPT;if (node.nextWaiter != null) // clean up if cancelledunlinkCancelledWaiters();if (interruptMode != 0)reportInterruptAfterWait(interruptMode); }

可以看到因為ConditionObject是AQS內(nèi)部類,可以獲取到外部類的數(shù)據(jù),調(diào)用await將線程放進條件隊列,然后同樣調(diào)用LockSupport類的park方法進行阻塞。

Condition對象調(diào)用signal或者signalAll方法時:

// 將條件隊列中第一個有效的元素移除并且添加到同步隊列中 private void doSignal(Node first) {do {if ( (firstWaiter = first.nextWaiter) == null)lastWaiter = null;first.nextWaiter = null;// 將條件隊列中等待最久的那個有效元素添加到同步隊列中} while (!transferForSignal(first) &&(first = firstWaiter) != null); }// 將條件隊列中的節(jié)點轉(zhuǎn)換到同步隊列中 final boolean transferForSignal(Node node) {// 如果節(jié)點的等待狀態(tài)不能被修改,說明當前線程已經(jīng)被取消等待if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))return false;// 加入到同步隊列中,并且嘗試將前驅(qū)節(jié)點設(shè)置為可喚醒狀態(tài)Node p = enq(node); int ws = p.waitStatus;// 如果前驅(qū)節(jié)點不需要喚醒,或者設(shè)置狀態(tài)為‘喚醒’失敗,則喚醒線程時期重新爭奪同步狀態(tài)if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))LockSupport.unpark(node.thread);return true; }

singal方法將節(jié)點放回同步隊列尾端,調(diào)用enq方法,該方法在AQS的時候分析過,該方法使用了死循環(huán), 即以自旋方式將節(jié)點插入隊列,如果失敗則不停的嘗試, 直到成功為止,運用到了樂觀鎖的原理,該方法也負責在隊列為空時, 初始化隊列。

為什么要有Condition呢?

在synchronized中,我們可以調(diào)用object.await和object.notify,讓線程等待和喚醒,但方法僅在synchronized中可以使用。通過Condition能夠更加精細的控制多線程的休眠與喚醒,synchronized相比ReentrantLock、ReadWriteLock等實現(xiàn)了Lock接口和內(nèi)含繼承AQS類的子類的鎖來說,synchronized顯得笨重,不夠靈活,適合小段代碼使用。

condition.signal和object.notify區(qū)別

  • obj.notify();? ?隨機喚醒一個處于等待狀態(tài)的線程,可能有多個線程處于等待狀態(tài),繼續(xù)執(zhí)行wait后面的代碼。與synchronized同步關(guān)鍵字配合
  • condition.signal(); 喚醒在同條件隊列的線程,與Lock配合

使用要求:

  • signal()、await()、signalAll()方法使用之前必須要先進行l(wèi)ock()獲取鎖,類似使用Object的notify()、wait()、notifyAll()之前必須要對Object對象進行synchronized操作,且兩類方法不能混合使用,否則都會拋IIlegalMonitorStateException。

Synchronized和Lock比較

  • Synchronized是關(guān)鍵字,內(nèi)置語言實現(xiàn),Lock是接口。
  • Synchronized在線程發(fā)生異常時會自動釋放鎖,因此不會發(fā)生異常死鎖。Lock異常時不會自動釋放鎖,所以需要在finally中實現(xiàn)釋放鎖。
  • Lock跟Synchronized可以在線程sleep,await,wait的時候響應中斷,但是Lock還可以在等待獲取鎖的時候響應中斷,對應的是lockInterruptibly()方法,而Synchronized只能一直等著。
  • Lock可以使用讀鎖提高多線程讀效率。

關(guān)系圖:

重入鎖

可重入就是說某個線程已經(jīng)獲得某個鎖,可以再次獲取鎖而不會出現(xiàn)死鎖。

為什么需要再次獲取鎖呢?

一個線程在執(zhí)行一個帶鎖的方法,該方法中又調(diào)用了另一個需要相同鎖的方法,則該線程可以直接執(zhí)行調(diào)用的方法,而無需重新獲得鎖,從而避免了死鎖。

實現(xiàn)原理

通過為每個鎖關(guān)聯(lián)一個請求計數(shù)器和一個獲得該鎖的線程。該計數(shù)器不是AQS的state,當計數(shù)器為0時,認為鎖是未被占用的。線程請求一個未被占用的鎖時,JVM將記錄該線程并將請求計數(shù)器設(shè)置為1,此時該線程就獲得了鎖,當該線程再次請求這個鎖,計數(shù)器將遞增,當線程退出同步方法或者同步代碼塊時,計數(shù)器將遞減,當計數(shù)器為0時,線程就釋放了該對象,其他線程才能獲取該鎖。

重入鎖有:

  • synchronized
  • ReentrantLock
  • ReentrantReadWriteLock

兩者區(qū)別

  • synchronized是獨占鎖,加鎖和解鎖的過程自動進行,易于操作,但不夠靈活。ReentrantLock也是獨占鎖,加鎖和解鎖的過程需要手動進行,不易操作,但非常靈活。
  • synchronized可重入,因為加鎖和解鎖自動進行,不必擔心最后是否釋放鎖;ReentrantLock也可重入,但加鎖和解鎖需要手動進行,且次數(shù)需一樣,否則其他線程無法獲得鎖。
  • synchronized不可響應中斷,一個線程獲取不到鎖就一直等著;ReentrantLock可以相應中斷。

ReentrantLock

ReentrantLock的內(nèi)部類Sync繼承了AQS,分為公平鎖FairSync和非公平鎖NonfairSync。

Lock lock=new ReentrantLock();//默認非公平鎖 Lock lock=new ReentrantLock(true);//公平鎖 Lock lock=new ReentrantLock(false);//非公平鎖 getHoldCount() 查詢當前線程保持此鎖的次數(shù),也就是執(zhí)行此線程執(zhí)行l(wèi)ock方法的次數(shù)。getQueueLength()返回正等待獲取此鎖的線程數(shù),比如啟動10個線程,1個線程獲得鎖,此時返回的是9。getWaitQueueLength(Condition condition)返回在該條件隊列的線程數(shù)。hasWaiters(Condition condition) 查詢該條件隊列是否有等待線程。hasQueuedThread(Thread thread) 查詢指定的線程是否正在等待獲取Lock鎖。hasQueuedThreads() 是否有線程等待此鎖isFair() 該鎖是否公平鎖isHeldByCurrentThread() 當前線程是否保持鎖鎖定,線程的執(zhí)行l(wèi)ock方法的前后分別是false和trueisLock() 此鎖是否有任意線程占用lockInterruptibly() 如果當前線程未被中斷,獲取鎖tryLock() 線程嘗試獲取鎖,如果獲取成功,返回 true,否則返回 falsetryLock(long timeout,TimeUnit unit) 線程如果在指定等待時間內(nèi)獲得了鎖,就返回true,否則返回 false

ReentrantReadWriteLock

Java并發(fā)包中ReadWriteLock是一個接口,主要有兩個方法,如下:

public interface ReadWriteLock {//返回讀鎖Lock readLock();//返回寫鎖Lock writeLock(); }

ReetrantReadWriteLock實現(xiàn)了ReadWriteLock接口并添加了可重入的特性。

有兩個鎖,一個是讀操作相關(guān)的鎖,稱為共享鎖;一個是寫相關(guān)的鎖,稱為排他鎖。

讀寫鎖的機制:

  • "讀-讀" 不互斥
  • "讀-寫" 互斥
  • "寫-寫" 互斥

線程進入讀鎖的前提條件:

  • 沒有其他線程的寫鎖或者有寫請求,但調(diào)用線程和持有鎖的線程是同一個。

線程進入寫鎖的前提條件:

  • 沒有其他線程的讀鎖
  • 沒有其他線程的寫鎖

3個特性:

  • 公平選擇性:支持非公平(默認)和公平的鎖獲取方式,吞吐量還是非公平優(yōu)于公平。
  • 重進入:讀鎖和寫鎖都支持線程重進入。
  • 鎖降級: 重入允許從寫入鎖降級為讀取鎖,其實現(xiàn)方式是:先獲取寫入鎖,然后獲取讀取鎖,最后釋放寫入鎖。但是,從讀取鎖升級到寫入鎖是不可能的。

為什么需要鎖降級:

線程A獲取寫鎖然后操作完變量x(后面我們還要利用變量x來進行一些操作),如果此時沒有獲取讀鎖然后釋放寫鎖,就可能發(fā)生其他線程獲取寫鎖,然后更新了變量x,從而讓我們后面用變量x的操作發(fā)生錯誤。如果有了讀鎖,其他線程就獲取不了寫鎖,而能獲取讀鎖,提高效率也不會發(fā)生錯誤。

?

?

?

?

?

?

?

?

?

?

總結(jié)

以上是生活随笔為你收集整理的多线程—Lock、Condition、ReentrantLock、ReentrantReadWriteLock的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 99久久99久久久精品棕色圆 | 欧美 日韩 国产 成人 在线观看 | 三级欧美视频 | 日韩国产精品一区二区三区 | 97人妻一区二区精品视频 | 国产人成视频在线观看 | 91 免费看片 | 天天操综合网 | 人妻互换一区二区三区四区五区 | 国产麻豆精品在线观看 | 人人爽爽人人 | 人人射影院 | 那里有毛片看 | 免费看的黄网站 | 日韩人妻精品一区二区三区 | 黄色录像片子 | 欧美一区日韩一区 | 在线观看黄av | 天天射日日操 | 欧美少妇18p | 少妇又色又紧又爽又刺激视频 | 好吊色视频988gao在线观看 | 在线a天堂| 嫩草影院在线观看视频 | 国产农村妇女精品久久久 | 96人xxxxxxxxx69 | 黄色片免费视频 | 久久精品国产一区二区电影 | 夜色网| 啪啪导航 | 国产做受麻豆动漫 | 久久精品激情 | 久久毛片视频 | 嫩模被强到高潮呻吟不断 | 好吊一区二区三区视频 | 亚洲黄色av | 手机免费在线观看av | 亚洲AV无码成人国产精品色 | 欧美第一页浮力影院 | 韩国美女被c | 国产精品999. | 国产成人精品综合在线观看 | 日本在线资源 | 国产午夜精品久久久久久久久久 | 国内久久精品视频 | 精品视频大全 | 亚洲视频不卡 | 免费日韩一区 | 19韩国主播青草vip | 少妇被躁爽到高潮无码人狍大战 | 深夜福利视频在线 | 福利免费在线观看 | 欧美性网址 | 污污视频在线观看网站 | 蜜桃视频导航 | 午夜激情网站 | 香蕉久久久久 | 曰本丰满熟妇xxxx性 | a猛片免费播放 | 波多野结衣一区二区三区 | 丁香五香天堂网 | 国产成年人视频网站 | 免费91看片 | aaaa级片 | 亚洲va国产va天堂va久久 | 亚洲美女自拍偷拍 | 欧美日韩人妻精品一区二区 | 免费一级a毛片夜夜看 | 毛片基地在线观看 | av片免费在线播放 | 日韩视频在线观看一区 | 亚洲一区二区三区免费在线观看 | 国产a不卡 | jizz在线观看视频 | 日本精品二区 | 在线免费观看黄视频 | 日韩成人无码影院 | 激情视频激情小说 | 激情伦成人综合小说 | 日韩午夜免费视频 | 一级片在线 | 九色精品在线 | 欧美一区二区黄色 | 天天干夜夜夜 | 在线免费观看日韩 | 在线免费av网 | 老牛影视少妇在线观看 | 疯狂伦交 | 国产三区在线成人av | 日韩精品在线视频观看 | 日本中文字幕视频在线 | 2020av在线 | 国产66页 | 51国产偷自视频区视频 | 国产特级av | 99久久精品无免国产免费 | 国产精品一区二区三区四区五区 | 国产高清久久久 | 99久久久国产精品无码网爆 |