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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

并发编程-19AQS同步组件之重入锁ReentrantLock、 读写锁ReentrantReadWriteLock、Condition

發(fā)布時(shí)間:2025/3/21 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 并发编程-19AQS同步组件之重入锁ReentrantLock、 读写锁ReentrantReadWriteLock、Condition 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

  • J.U.C腦圖
  • ReentrantLock概述
  • ReentrantLock 常用方法
  • synchronized 和 ReentrantLock的比較
  • ReentrantLock示例
  • 讀寫(xiě)鎖ReentrantReadWriteLock
    • 例子
  • StampedLock
    • 示例
  • Condition
    • 示例
  • 代碼

J.U.C腦圖



ReentrantLock概述

重入鎖ReentrantLock,顧名思義,就是支持重進(jìn)入的鎖,它表示該鎖能夠支持一個(gè)線程對(duì)
資源的重復(fù)加鎖,而不會(huì)造成自己阻塞自己。

重進(jìn)入是指任意線程在獲取到鎖之后能夠再次獲取該鎖而不會(huì)被鎖所阻塞

ReentrantLock雖然沒(méi)能像synchronized關(guān)鍵字一樣支持隱式的重進(jìn)入,但是在調(diào)用lock()方
法時(shí),已經(jīng)獲取到鎖的線程,能夠再次調(diào)用lock()方法獲取鎖而不被阻塞。


除此之外,該鎖的還支持獲取鎖時(shí)的公平和非公平性選擇。實(shí)際上,公平的鎖機(jī)制往往沒(méi)有非公平的效率高,但是,并不是任何場(chǎng)景都是以TPS作為唯一的指標(biāo),公平鎖能夠減少“饑餓”發(fā)生的概率,等待越久的請(qǐng)求越是能夠得到優(yōu)先滿(mǎn)足。看使用場(chǎng)景。

公平性鎖保證了鎖的獲取按照FIFO原則,而代價(jià)是進(jìn)行大量的線程切換。非公平性鎖雖然可能造成線程“饑餓”,但極少的線程切換,保證了其更大的吞吐量。


在Java里一共有兩類(lèi)鎖, 一類(lèi)是synchornized同步鎖,還有一種是JUC里提供的鎖Lock,Lock是個(gè)接口,其核心實(shí)現(xiàn)類(lèi)就是ReentrantLock。

ReentrantLock實(shí)現(xiàn) ,主要是采用自旋鎖,循環(huán)調(diào)用CAS操作來(lái)實(shí)現(xiàn)加鎖,避免了使線程進(jìn)入內(nèi)核態(tài)的阻塞狀態(tài)

ReentrantLock獨(dú)有的功能

  • 可指定是公平鎖還是非公平鎖,所謂公平鎖就是先等待的線程先獲得鎖
  • 提供了一個(gè)Condition類(lèi),可以分組喚醒需要喚醒的線程
  • 提供能夠中斷等待鎖的線程的機(jī)制,lock.lockInterruptibly()

ReentrantLock 常用方法

void lock() //加鎖 void unlock() //釋放鎖 boolean isHeldByCurrentThread(); // 當(dāng)前線程是否保持鎖定 boolean isLocked() // 是否存在任意線程持有鎖資源 void lockInterruptbly() // 如果當(dāng)前線程未被中斷,則獲取鎖定;如果已中斷,則拋出異常(InterruptedException) int getHoldCount() // 查詢(xún)當(dāng)前線程保持此鎖定的個(gè)數(shù),即調(diào)用lock()方法的次數(shù) int getQueueLength() // 返回正等待獲取此鎖定的預(yù)估線程數(shù) int getWaitQueueLength(Condition condition) // 返回與此鎖定相關(guān)的約定condition的線程預(yù)估數(shù) boolean hasQueuedThread(Thread thread) // 當(dāng)前線程是否在等待獲取鎖資源 boolean hasQueuedThreads() // 是否有線程在等待獲取鎖資源 boolean hasWaiters(Condition condition) // 是否存在指定Condition的線程正在等待鎖資源 boolean isFair() // 是否使用的是公平鎖

synchronized 和 ReentrantLock的比較

synchornizedReentrantLock
可重入性可重入(都是同一個(gè)線程每進(jìn)入一次,鎖的計(jì)數(shù)器都自增1,所以要等到鎖的計(jì)數(shù)器下降為0時(shí)才能釋放鎖)可重入
鎖的實(shí)現(xiàn)JVM實(shí)現(xiàn),操作系統(tǒng)級(jí)別JDK實(shí)現(xiàn)
性能在引入偏向鎖、輕量級(jí)鎖(自旋鎖)后性能大大提升,官方建議無(wú)特殊要求時(shí)盡量使用synchornized,并且新版本的一些jdk源碼都由之前的ReentrantLock改成了synchornized與優(yōu)化后的synchornized相差不大
功能區(qū)別方便簡(jiǎn)潔,由編譯器負(fù)責(zé)加鎖和釋放鎖 ,不會(huì)產(chǎn)生死鎖需手工操作鎖的加鎖和釋放,忘記釋放會(huì)產(chǎn)生死鎖
鎖粒度粗粒度,不靈活細(xì)粒度,可靈活控制
可否指定公平鎖不可以可以
可否放棄鎖不可以可以

順便說(shuō)下自旋鎖:是指當(dāng)一個(gè)線程在獲取鎖的時(shí)候,如果鎖已經(jīng)被其它線程獲取,那么該線程將循環(huán)等待,然后不斷的判斷鎖是否能夠被成功獲取,直到獲取到鎖才會(huì)退出循環(huán)。

那該如何選擇呢?

如果需要實(shí)現(xiàn)ReenTrantLock的三個(gè)獨(dú)有功能時(shí),就選擇使用ReenTrantLock, 通常情況下synchronized就能夠滿(mǎn)足了,而且使用起來(lái)簡(jiǎn)單,由JVM管理,不會(huì)產(chǎn)生死鎖。


ReentrantLock示例

我們把使用synchronized來(lái)確保線程安全的例子,使用ReentrantLock來(lái)實(shí)現(xiàn)下

多次運(yùn)行: 線程安全


讀寫(xiě)鎖ReentrantReadWriteLock

可重入鎖ReentrantLock是排他鎖,這些鎖在同一時(shí)刻只允許一個(gè)線程進(jìn)行訪問(wèn)

而讀寫(xiě)鎖ReentrantReadWriteLock在同一時(shí)刻可以允許多個(gè)讀線程訪問(wèn),但是在寫(xiě)線程訪問(wèn)時(shí),所有的讀線程和其他寫(xiě)線程均被阻塞。即ReentrantReadWriteLock允許多個(gè)讀線程同時(shí)訪問(wèn),但不允許寫(xiě)線程和讀線程、寫(xiě)線程和寫(xiě)線程同時(shí)訪問(wèn)

在沒(méi)有任何讀寫(xiě)鎖的時(shí)候才能取得寫(xiě)入的鎖,可用于實(shí)現(xiàn)悲觀讀取

讀寫(xiě)鎖維護(hù)了一對(duì)鎖,一個(gè)讀鎖和一個(gè)寫(xiě)鎖,通過(guò)分離讀鎖和寫(xiě),使得并發(fā)性相比一般的排他鎖有了很大提升。


例子

假設(shè)現(xiàn)在有一個(gè)類(lèi),里面有一個(gè)map集合,希望在對(duì)其讀寫(xiě)的時(shí)候能夠進(jìn)行一些線程安全的保護(hù),這時(shí)我們就可以使用到ReentrantReadWriteLock


StampedLock

StampedLock是Java8引入的一種新的鎖機(jī)制,是讀寫(xiě)鎖的一個(gè)改進(jìn)版本,讀寫(xiě)鎖雖然分離了讀和寫(xiě)的功能,使得讀與讀之間可以完全并發(fā),但是讀和寫(xiě)之間依然是沖突的,讀鎖會(huì)完全阻塞寫(xiě)鎖,它使用的依然是悲觀的鎖策略。如果有大量的讀線程,它也有可能引起寫(xiě)線程的饑餓。而StampedLock則提供了一種樂(lè)觀的讀策略,這種樂(lè)觀策略的鎖非常類(lèi)似于無(wú)鎖的操作,使得樂(lè)觀鎖完全不會(huì)阻塞寫(xiě)線程。

示例

運(yùn)行結(jié)果: 線程安全


Condition

任意一個(gè)Java對(duì)象,都擁有一組監(jiān)視器方法(定義在java.lang.Object上),主要包括wait()、 wait(long timeout)、notify()以及notifyAll()方法,這些方法與synchronized同步關(guān)鍵字配合,可以實(shí)現(xiàn)等待/通知模式。Condition接口也提供了類(lèi)似Object的監(jiān)視器方法,與Lock配合可以實(shí)現(xiàn)等待/通知模式,但是這兩者在使用方式以及功能特性上還是有差別的。

Condition定義了等待/通知兩種類(lèi)型的方法,當(dāng)前線程調(diào)用這些方法時(shí),需要提前獲取到 Condition對(duì)象關(guān)聯(lián)的鎖。Condition對(duì)象是由Lock對(duì)象(調(diào)用Lock對(duì)象的newCondition()方法)創(chuàng)建出來(lái)的,換句話(huà)說(shuō),Condition是依賴(lài)Lock對(duì)象的。

獲取一個(gè)Condition必須通過(guò)Lock的newCondition()方法。


示例

Condition是一個(gè)多線程間協(xié)調(diào)通信的工具類(lèi),使得某個(gè)或者某些線程一起等待某個(gè)條件(Condition),只有當(dāng)該條件具備( signal 或者 signalAll方法被調(diào)用)時(shí) ,這些等待線程才會(huì)被喚醒,從而重新?tīng)?zhēng)奪鎖。

Condition可以非常靈活的操作線程的喚醒,下面是一個(gè)線程等待與喚醒的例子,其中用1、2、3、4序號(hào)標(biāo)出了日志輸出順序

輸出:


代碼

https://github.com/yangshangwei/ConcurrencyMaster

總結(jié)

以上是生活随笔為你收集整理的并发编程-19AQS同步组件之重入锁ReentrantLock、 读写锁ReentrantReadWriteLock、Condition的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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