最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

關(guān)于ReadWriteLock讀寫(xiě)鎖的使用及說(shuō)明

 更新時(shí)間:2025年06月30日 09:22:04   作者:找不到、了  
這篇文章主要介紹了關(guān)于ReadWriteLock讀寫(xiě)鎖的使用及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

ReentrantReadWriteLock實(shí)現(xiàn)了ReadWriteLock接口。位于java.util.concurrent.locks;

1、普通鎖

讀寫(xiě)互斥,如ReentrantLock。

1.1、原理

  • 普通鎖是排他鎖(Exclusive Lock):無(wú)論讀還是寫(xiě),同一時(shí)刻只能有一個(gè)線(xiàn)程持有鎖。
  • 所有操作互斥:即使多個(gè)線(xiàn)程只是讀取數(shù)據(jù),普通鎖也會(huì)阻塞其他線(xiàn)程。

代碼示例:

ReentrantLock lock = new ReentrantLock();

void read() {
    lock.lock();
    try {
        // 讀取數(shù)據(jù)
    } finally {
        lock.unlock();
    }
}

void write() {
    lock.lock();
    try {
        // 寫(xiě)入數(shù)據(jù)
    } finally {
        lock.unlock();
    }
}

1.2、特點(diǎn)

  • 讀線(xiàn)程會(huì)阻塞其他讀線(xiàn)程:即使沒(méi)有寫(xiě)操作,讀線(xiàn)程之間也不能并發(fā)。
  • 性能低:在高并發(fā)讀場(chǎng)景下,資源利用率低。

2、ReadWriteLock

讀寫(xiě)分離機(jī)制。

  • 基于 AQS:通過(guò)state字段的高位和低位分別管理讀鎖和寫(xiě)鎖。
  • 共享鎖(Shared):允許多個(gè)線(xiàn)程同時(shí)讀。
  • 排他鎖(Exclusive):寫(xiě)操作獨(dú)占鎖。

2.1、核心思想

規(guī)則讀鎖與讀鎖不互斥讀鎖與寫(xiě)鎖互斥。寫(xiě)鎖與寫(xiě)鎖互斥。

讀鎖(共享鎖)

  • 多個(gè)線(xiàn)程可同時(shí)持有讀鎖。
  • 獲取讀鎖時(shí),需確保沒(méi)有寫(xiě)鎖存在。
  • 讀鎖可重入(同一線(xiàn)程多次獲取讀鎖時(shí),state高位增加)。

寫(xiě)鎖(排他鎖)

  • 寫(xiě)鎖獨(dú)占,阻塞所有讀和寫(xiě)操作。
  • 寫(xiě)鎖可重入(同一線(xiàn)程多次獲取寫(xiě)鎖時(shí),state低位增加)。
  • 寫(xiě)鎖可降級(jí)為讀鎖(但不能升級(jí)為寫(xiě)鎖)。

鎖升級(jí)/降級(jí)規(guī)則

  • 不允許升級(jí):讀鎖不能直接升級(jí)為寫(xiě)鎖(會(huì)破壞公平性,可能導(dǎo)致死鎖)。
  • 允許降級(jí):寫(xiě)鎖可以降級(jí)為讀鎖(需顯式釋放寫(xiě)鎖后獲取讀鎖)。

代碼示例:

ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
Lock readLock = readWriteLock.readLock();
Lock writeLock = readWriteLock.writeLock();

void read() {
    readLock.lock();
    try {
        // 讀取數(shù)據(jù)(多個(gè)線(xiàn)程可同時(shí)讀)
    } finally {
        readLock.unlock();
    }
}

void write() {
    writeLock.lock();
    try {
        // 寫(xiě)入數(shù)據(jù)(獨(dú)占)
    } finally {
        writeLock.unlock();
    }
}

為什么讀鎖和寫(xiě)鎖可以“部分共存”?

  • 讀鎖不阻塞其他讀鎖:因?yàn)樽x操作不會(huì)修改數(shù)據(jù),多個(gè)線(xiàn)程讀取共享數(shù)據(jù)是安全的。
  • 寫(xiě)鎖阻塞所有讀寫(xiě):寫(xiě)操作需要獨(dú)占數(shù)據(jù),防止臟讀和數(shù)據(jù)不一致。

2.2、特點(diǎn)

1、高效

適合高并發(fā)讀的場(chǎng)景。

  • 普通鎖:多個(gè)讀線(xiàn)程互相阻塞,吞吐量低。
  • 讀寫(xiě)鎖:多個(gè)讀線(xiàn)程可并發(fā)讀取,吞吐量高。

2、緩存讀取和更新

class Cache {
    private Object data;
    private ReadWriteLock lock = new ReentrantReadWriteLock();

    void get() {
        lock.readLock().lock();
        try {
            // 多個(gè)線(xiàn)程可同時(shí)讀取
            return data;
        } finally {
            lock.readLock().unlock();
        }
    }

    void put(Object newData) {
        lock.writeLock().lock();
        try {
            // 寫(xiě)入時(shí)獨(dú)占
            data = newData;
        } finally {
            lock.writeLock().unlock();
        }
    }
}
  • 優(yōu)勢(shì):緩存讀取頻繁,寫(xiě)入較少,使用讀寫(xiě)鎖可大幅提升并發(fā)性能。

2.3、鎖共存

寫(xiě)鎖不能與讀鎖或?qū)戞i共存。具體是為什么,可參考以下數(shù)據(jù)一致性和state字段來(lái)進(jìn)行分析。

1. 數(shù)據(jù)一致性要求

寫(xiě)操作必須獨(dú)占:如果允許寫(xiě)鎖與讀鎖或?qū)戞i共存,可能導(dǎo)致:

  • 臟讀:讀線(xiàn)程讀到未提交的數(shù)據(jù)。
  • 數(shù)據(jù)不一致:多個(gè)寫(xiě)線(xiàn)程同時(shí)修改數(shù)據(jù),導(dǎo)致結(jié)果不可預(yù)測(cè)。

2. 內(nèi)部實(shí)現(xiàn)限制

讀寫(xiě)鎖的實(shí)現(xiàn)

  • 使用一個(gè)int類(lèi)型的state字段,高16位表示讀鎖數(shù)量,低16位表示寫(xiě)鎖重入次數(shù)。
  • 寫(xiě)鎖獲取時(shí):必須確保當(dāng)前沒(méi)有讀鎖或?qū)戞i。
  • 讀鎖獲取時(shí):必須確保當(dāng)前沒(méi)有寫(xiě)鎖。

2.4、關(guān)鍵字段

  • state:高位(32位)表示讀鎖數(shù)量,低位(32位)表示寫(xiě)鎖重入次數(shù)。
  • readLockwriteLock:分別管理讀鎖和寫(xiě)鎖的獲取與釋放。

以下是常用的方法:

  • readLock().lock():嘗試獲取共享鎖。
  • writeLock().lock():嘗試獲取排他鎖。
  • readLock().unlock()writeLock().unlock():釋放對(duì)應(yīng)鎖。

2.5、獲取流程

1、寫(xiě)鎖

  • 檢查當(dāng)前是否有寫(xiě)鎖(通過(guò)exclusiveCount判斷)。
  • 檢查是否有讀鎖(通過(guò)sharedCount判斷)。
  • 如果沒(méi)有讀鎖和寫(xiě)鎖,則設(shè)置寫(xiě)鎖狀態(tài)。
  • 否則,將線(xiàn)程加入等待隊(duì)列。

2、讀鎖

  • 檢查當(dāng)前是否有寫(xiě)鎖。
  • 如果沒(méi)有寫(xiě)鎖,則嘗試增加讀鎖計(jì)數(shù)。
  • 如果有寫(xiě)鎖或讀鎖溢出,則將線(xiàn)程加入等待隊(duì)列。

小結(jié)

如何選擇哪種鎖,可根據(jù)以下場(chǎng)景進(jìn)行分析:

選擇普通鎖

  • 數(shù)據(jù)操作簡(jiǎn)單(如單次寫(xiě)入后只讀)。
  • 不需要區(qū)分讀寫(xiě)操作。

選擇讀寫(xiě)鎖

  • 讀操作遠(yuǎn)多于寫(xiě)操作(如緩存、配置中心)。
  • 需要提升讀并發(fā)性能。

對(duì)比

普通鎖 vsReadWriteLock:

3、寫(xiě)鎖饑餓

3.1、原因

1. 優(yōu)先級(jí)

  • ReentrantReadWriteLock 默認(rèn)是非公平模式fair=false)。
  • 讀鎖的優(yōu)先級(jí)更高:在非公平模式下,讀鎖可以“插隊(duì)”獲取鎖,即使有等待的寫(xiě)線(xiàn)程。
  • 寫(xiě)鎖需要獨(dú)占鎖:寫(xiě)操作必須阻塞所有讀和寫(xiě),因此寫(xiě)線(xiàn)程會(huì)一直等待,直到所有讀線(xiàn)程釋放讀鎖。

2. 等待隊(duì)列機(jī)制

AQS(AbstractQueuedSynchronizer)維護(hù)一個(gè) FIFO 隊(duì)列

非公平模式下

  • 讀線(xiàn)程可以“插隊(duì)”獲取鎖(無(wú)需排隊(duì))。
  • 寫(xiě)線(xiàn)程只能按順序等待,直到?jīng)]有讀線(xiàn)程。

示例:

ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

// 線(xiàn)程 A: 讀線(xiàn)程
lock.readLock().lock();
try {
    while (true) {
        // 持續(xù)讀?。ú会尫抛x鎖)
    }
} finally {
    lock.readLock().unlock();
}

// 線(xiàn)程 B: 寫(xiě)線(xiàn)程
lock.writeLock().lock(); // 被阻塞,永遠(yuǎn)無(wú)法獲取寫(xiě)鎖

3.2、實(shí)現(xiàn)原理

1. 寫(xiě)鎖獲取流程

檢查當(dāng)前是否有寫(xiě)鎖(通過(guò)exclusiveCount判斷)。

檢查是否有讀鎖(通過(guò)sharedCount判斷)。

非公平模式下

  • 如果沒(méi)有寫(xiě)鎖,且當(dāng)前線(xiàn)程可以插隊(duì)(無(wú)需等待),則直接獲取寫(xiě)鎖。
  • 如果有讀鎖或?qū)戞i,則將線(xiàn)程加入等待隊(duì)列。

公平模式下

  • 寫(xiě)線(xiàn)程必須按順序等待,即使沒(méi)有讀鎖。

2. 寫(xiě)鎖釋放流程

  1. 釋放寫(xiě)鎖后,喚醒等待隊(duì)列中的線(xiàn)程。

非公平模式下

  • 新來(lái)的讀線(xiàn)程可能再次插隊(duì)獲取讀鎖。
  • 寫(xiě)線(xiàn)程仍需等待所有讀線(xiàn)程釋放讀鎖。

3.3、避免寫(xiě)鎖饑餓

1. 使用公平模式(Fair Mode)

  • 配置公平鎖new ReentrantReadWriteLock(true)

效果

  • 寫(xiě)線(xiàn)程按順序獲取鎖,不會(huì)被讀線(xiàn)程插隊(duì)。
  • 優(yōu)點(diǎn):避免寫(xiě)鎖饑餓。
  • 缺點(diǎn):性能略低(讀線(xiàn)程無(wú)法插隊(duì))。

代碼示例:

ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true); // 公平模式

void read() {
    lock.readLock().lock();
    try {
        // 讀取數(shù)據(jù)
    } finally {
        lock.readLock().unlock();
    }
}

void write() {
    lock.writeLock().lock();
    try {
        // 寫(xiě)入數(shù)據(jù)
    } finally {
        lock.writeLock().unlock();
    }
}

公平模式下和非公平模式下:

2.限制讀鎖的持有時(shí)間

避免讀線(xiàn)程長(zhǎng)期占用讀鎖

  • 在業(yè)務(wù)邏輯中控制讀鎖的持有時(shí)間。
  • 避免在讀鎖內(nèi)執(zhí)行長(zhǎng)時(shí)間操作。

3. 使用StampedLock

在Java 8+,StampedLock提供更靈活的讀寫(xiě)鎖策略

  • 支持樂(lè)觀讀鎖(不阻塞寫(xiě)鎖)。
  • 支持寫(xiě)鎖優(yōu)先級(jí)(避免讀鎖插隊(duì))。

代碼示例:

StampedLock lock = new StampedLock();

void read() {
    long stamp = lock.tryOptimisticRead();
    if (lock.validate(stamp)) {
        // 樂(lè)觀讀?。ú蛔枞麑?xiě)鎖)
    }
}

void write() {
    long stamp = lock.writeLock();
    try {
        // 寫(xiě)入數(shù)據(jù)
    } finally {
        lock.unlockWrite(stamp);
    }
}

總結(jié)

通過(guò)合理選擇鎖策略,可以在高并發(fā)場(chǎng)景下平衡性能與公平性!

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • spring boot + jpa + kotlin入門(mén)實(shí)例詳解

    spring boot + jpa + kotlin入門(mén)實(shí)例詳解

    這篇文章主要介紹了spring boot + jpa + kotlin入門(mén)實(shí)例詳解 ,需要的朋友可以參考下
    2017-07-07
  • Java中實(shí)現(xiàn)OCR識(shí)別讀取圖片中的文字

    Java中實(shí)現(xiàn)OCR識(shí)別讀取圖片中的文字

    圖片內(nèi)容一般無(wú)法編輯,如果想要讀取圖片中的文本,我們需要用到OCR工具,本文將介紹如何在Java中實(shí)現(xiàn)OCR識(shí)別讀取圖片中的文字,文中通過(guò)代碼示例介紹的非常詳細(xì),需要的朋友可以參考下
    2024-04-04
  • Java多線(xiàn)程模擬售票程序和線(xiàn)程安全問(wèn)題

    Java多線(xiàn)程模擬售票程序和線(xiàn)程安全問(wèn)題

    本篇文章給大家分享了Java多線(xiàn)程模擬售票程序和線(xiàn)程安全問(wèn)題的相關(guān)知識(shí)點(diǎn),對(duì)此有興趣的朋友可以參考學(xué)習(xí)下。
    2018-05-05
  • 詳解 Java 中 equals 和 == 的區(qū)別

    詳解 Java 中 equals 和 == 的區(qū)別

    這篇文章主要介紹了詳解 Java 中 equals 和 == 的區(qū)別的相關(guān)資料,equals 和 == 都是用來(lái)檢測(cè)兩個(gè)字符串是否相等,返回值也都是布爾型,但是兩者在內(nèi)部比較的處理中卻不盡相同需要的朋友可以參考下
    2017-03-03
  • Java中@DS+@Transactional注解切換數(shù)據(jù)源失效解決方案

    Java中@DS+@Transactional注解切換數(shù)據(jù)源失效解決方案

    本文主要介紹了@DS+@Transactional注解切換數(shù)據(jù)源失效解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • 詳解Java回環(huán)屏障CyclicBarrier

    詳解Java回環(huán)屏障CyclicBarrier

    這篇文章主要介紹了Java回環(huán)屏障CyclicBarrier的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)Java,感興趣的朋友可以了解下
    2020-09-09
  • java實(shí)現(xiàn)簡(jiǎn)單的猜數(shù)字小游戲

    java實(shí)現(xiàn)簡(jiǎn)單的猜數(shù)字小游戲

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)簡(jiǎn)單猜數(shù)字小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-03-03
  • Java使用遞歸法解決漢諾塔問(wèn)題的代碼示例

    Java使用遞歸法解決漢諾塔問(wèn)題的代碼示例

    這篇文章主要介紹了Java使用遞歸法解決漢諾塔問(wèn)題的代碼示例,漢諾塔問(wèn)題是使用遞歸解決問(wèn)題的經(jīng)典范例,用到的算法非常簡(jiǎn)單,需要的朋友可以參考下
    2016-04-04
  • Java設(shè)計(jì)模式之策略模式示例詳解

    Java設(shè)計(jì)模式之策略模式示例詳解

    策略模式屬于Java?23種設(shè)計(jì)模式中行為模式之一,該模式定義了一系列算法,并將每個(gè)算法封裝起來(lái),使它們可以相互替換,且算法的變化不會(huì)影響使用算法的客戶(hù)。本文將通過(guò)示例詳細(xì)講解這一模式,需要的可以參考一下
    2022-03-03
  • Java8日期時(shí)間類(lèi)LocalDateTime比較大小舉例

    Java8日期時(shí)間類(lèi)LocalDateTime比較大小舉例

    LocalDate是Java?8中的日期類(lèi)之一,它表示一個(gè)日期,下面這篇文章主要給大家介紹了關(guān)于Java8日期時(shí)間類(lèi)LocalDateTime比較大小的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-05-05

最新評(píng)論

平远县| 榆社县| 昌江| 姚安县| 错那县| 罗甸县| 砀山县| 同仁县| 高邮市| 凤阳县| 上饶县| 淳化县| 霍山县| 闸北区| 衡山县| 明光市| 大城县| 沂源县| 淮安市| 南和县| 靖西县| 根河市| 汽车| 河北区| 武鸣县| 汪清县| 上犹县| 花莲市| 五指山市| 勐海县| 扶余县| 建德市| 北宁市| 河西区| 泽州县| 建始县| 张家界市| 旌德县| 克什克腾旗| 志丹县| 汉沽区|