亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java ReentrantLock的使用與應(yīng)用實(shí)戰(zhàn)

 更新時(shí)間:2025年09月29日 10:17:40   作者:IT橘子皮  
ReentrantLock是Java并發(fā)包中提供的一種可重入互斥鎖,它作為synchronized關(guān)鍵字的替代方案,提供了更靈活、更強(qiáng)大的線程同步機(jī)制,下面就來(lái)介紹一下ReentrantLock的實(shí)戰(zhàn)使用

ReentrantLock是Java并發(fā)包(java.util.concurrent.locks)中提供的一種可重入互斥鎖,它作為synchronized關(guān)鍵字的替代方案,提供了更靈活、更強(qiáng)大的線程同步機(jī)制。本文將全面解析ReentrantLock的核心特性、實(shí)現(xiàn)原理及實(shí)際應(yīng)用場(chǎng)景。

ReentrantLock概述與基本特性

ReentrantLock是Java 5引入的顯式鎖機(jī)制,它基于AQS(AbstractQueuedSynchronizer)框架實(shí)現(xiàn),提供了比synchronized更豐富的功能和控制能力。與synchronized相比,ReentrantLock具有以下顯著特點(diǎn):

  • ?可重入性?:同一線程可以多次獲得同一把鎖而不會(huì)被阻塞,每次獲取鎖后必須釋放相同次數(shù)的鎖
  • ?公平性選擇?:支持公平鎖和非公平鎖兩種策略,公平鎖按照線程請(qǐng)求順序分配鎖,非公平鎖允許"插隊(duì)"以提高吞吐量
  • ?靈活的鎖獲取方式?:提供嘗試非阻塞獲取鎖(tryLock)、可中斷獲取鎖(lockInterruptibly)和超時(shí)獲取鎖(tryLock with timeout)等方法
  • ?條件變量支持?:通過(guò)Condition接口實(shí)現(xiàn)多個(gè)等待隊(duì)列,比synchronized的wait/notify機(jī)制更精準(zhǔn)

從實(shí)現(xiàn)層級(jí)看,synchronized是JVM內(nèi)置的鎖機(jī)制,通過(guò)monitorenter/monitorexit字節(jié)碼指令實(shí)現(xiàn);而ReentrantLock是JDK API級(jí)別的鎖,基于AQS框架構(gòu)建。

ReentrantLock核心方法與使用

基礎(chǔ)鎖操作

ReentrantLock的基本使用模式遵循"加鎖-操作-釋放鎖"的流程,必須確保在finally塊中釋放鎖:

ReentrantLock lock = new ReentrantLock();
lock.lock();
try {
    // 臨界區(qū)代碼
} finally {
    lock.unlock();
}

這種顯式鎖管理相比synchronized需要更多注意,但提供了更精細(xì)的控制。

高級(jí)鎖獲取方式

  1. ?嘗試非阻塞獲取鎖(tryLock)??:

    立即返回獲取結(jié)果,不阻塞線程,適用于避免死鎖或快速失敗場(chǎng)景:

    if (lock.tryLock()) {
        try {
            // 臨界區(qū)代碼
        } finally {
            lock.unlock();
        }
    } else {
        // 執(zhí)行備選方案
    }
    
  2. ?超時(shí)獲取鎖?:

    在指定時(shí)間內(nèi)嘗試獲取鎖,避免無(wú)限期等待:

    if (lock.tryLock(2, TimeUnit.SECONDS)) {
        try {
            // 臨界區(qū)代碼
        } finally {
            lock.unlock();
        }
    }
    
  3. ?可中斷獲取鎖(lockInterruptibly)??:

    允許在等待鎖的過(guò)程中響應(yīng)中斷信號(hào):

    try {
        lock.lockInterruptibly();
        try {
            // 臨界區(qū)代碼
        } finally {
            lock.unlock();
        }
    } catch (InterruptedException e) {
        // 處理中斷
    }
    

鎖狀態(tài)查詢

ReentrantLock提供了一系列狀態(tài)查詢方法:

  • isLocked():查詢鎖是否被持有
  • isHeldByCurrentThread():當(dāng)前線程是否持有鎖
  • getHoldCount():當(dāng)前線程持有鎖的次數(shù)(重入次數(shù))
  • getQueueLength():等待獲取鎖的線程數(shù)

ReentrantLock實(shí)現(xiàn)原理

AQS框架基礎(chǔ)

ReentrantLock的核心實(shí)現(xiàn)依賴于AbstractQueuedSynchronizer(AQS),這是一個(gè)用于構(gòu)建鎖和同步器的框架。AQS內(nèi)部維護(hù)了:

  • volatile int state:同步狀態(tài),對(duì)于ReentrantLock,0表示未鎖定,>0表示鎖定狀態(tài)及重入次數(shù)
  • FIFO線程等待隊(duì)列:管理獲取鎖失敗的線程

公平鎖與非公平鎖實(shí)現(xiàn)

ReentrantLock通過(guò)兩種不同的Sync子類實(shí)現(xiàn)鎖策略:

  1. ?非公平鎖(默認(rèn))??:

    final void lock() {
        if (compareAndSetState(0, 1))  // 直接嘗試搶占
            setExclusiveOwnerThread(Thread.currentThread());
        else
            acquire(1);
    }
    

    新請(qǐng)求的線程可以直接插隊(duì)嘗試獲取鎖,不考慮等待隊(duì)列

  2. ?公平鎖?:

    protected final boolean tryAcquire(int acquires) {
        if (!hasQueuedPredecessors() &&  // 檢查是否有前驅(qū)節(jié)點(diǎn)
            compareAndSetState(0, acquires)) {
            setExclusiveOwnerThread(Thread.currentThread());
            return true;
        }
        // 可重入邏輯...
    }
    

    嚴(yán)格按照FIFO順序分配鎖,避免饑餓現(xiàn)象

鎖的獲取與釋放流程

  1. ?加鎖過(guò)程?:

    • 嘗試通過(guò)CAS修改state狀態(tài)
    • 成功則設(shè)置當(dāng)前線程為獨(dú)占線程
    • 失敗則構(gòu)造Node加入CLH隊(duì)列尾部,并阻塞線程
  2. ?釋放過(guò)程?:

    • 減少持有計(jì)數(shù)(state減1)
    • 當(dāng)state為0時(shí)完全釋放鎖
    • 喚醒隊(duì)列中的下一個(gè)等待線程

ReentrantLock實(shí)戰(zhàn)應(yīng)用

生產(chǎn)者-消費(fèi)者模型

使用ReentrantLock配合Condition實(shí)現(xiàn)高效的生產(chǎn)者-消費(fèi)者模式:

public class BoundedBuffer {
    private final ReentrantLock lock = new ReentrantLock();
    private final Condition notFull = lock.newCondition();
    private final Condition notEmpty = lock.newCondition();
    private final Object[] items = new Object[100];
    private int putPtr, takePtr, count;

    public void put(Object x) throws InterruptedException {
        lock.lock();
        try {
            while (count == items.length)
                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();
        }
    }
}

這種實(shí)現(xiàn)比synchronized+wait/notify更高效,因?yàn)榭梢跃珳?zhǔn)喚醒生產(chǎn)者或消費(fèi)者線程。

銀行轉(zhuǎn)賬避免死鎖

使用tryLock實(shí)現(xiàn)帶超時(shí)的轉(zhuǎn)賬操作,避免死鎖:

public boolean transfer(Account from, Account to, int amount, long timeout, TimeUnit unit) {
    long stopTime = System.nanoTime() + unit.toNanos(timeout);
    while (true) {
        if (from.getLock().tryLock()) {
            try {
                if (to.getLock().tryLock()) {
                    try {
                        if (from.getBalance() < amount)
                            throw new InsufficientFundsException();
                        from.withdraw(amount);
                        to.deposit(amount);
                        return true;
                    } finally {
                        to.getLock().unlock();
                    }
                }
            } finally {
                from.getLock().unlock();
            }
        }
        if (System.nanoTime() > stopTime)
            return false;
        Thread.sleep(fixedDelay);
    }
}

通過(guò)tryLock和超時(shí)機(jī)制,有效預(yù)防了死鎖風(fēng)險(xiǎn)。

可中斷的任務(wù)執(zhí)行

使用lockInterruptibly實(shí)現(xiàn)可中斷的任務(wù)執(zhí)行:

public class InterruptibleTask {
    private final ReentrantLock lock = new ReentrantLock();
    
    public void executeTask() throws InterruptedException {
        lock.lockInterruptibly();
        try {
            // 執(zhí)行可能長(zhǎng)時(shí)間運(yùn)行的任務(wù)
            while (!Thread.currentThread().isInterrupted()) {
                // 任務(wù)邏輯...
            }
        } finally {
            lock.unlock();
        }
    }
}

這種模式適用于需要支持任務(wù)取消的場(chǎng)景。

ReentrantLock與synchronized的對(duì)比

特性synchronizedReentrantLock
實(shí)現(xiàn)層級(jí)JVM內(nèi)置JDK API實(shí)現(xiàn)
鎖釋放自動(dòng)必須手動(dòng)調(diào)用unlock()
公平鎖支持僅非公平支持公平和非公平策略
可中斷獲取鎖不支持支持(lockInterruptibly)
超時(shí)獲取鎖不支持支持(tryLock with timeout)
條件變量單一等待隊(duì)列支持多個(gè)Condition
鎖狀態(tài)查詢有限提供豐富查詢方法
性能Java 6+優(yōu)化復(fù)雜場(chǎng)景下表現(xiàn)更好
代碼簡(jiǎn)潔性較低(需手動(dòng)管理)
適用場(chǎng)景簡(jiǎn)單同步復(fù)雜同步需求

在Java 6及以后版本中,synchronized經(jīng)過(guò)鎖升級(jí)(偏向鎖→輕量級(jí)鎖→重量級(jí)鎖)優(yōu)化,性能與ReentrantLock差距已不明顯。因此,簡(jiǎn)單場(chǎng)景推薦使用synchronized,復(fù)雜場(chǎng)景才考慮ReentrantLock。

ReentrantLock最佳實(shí)踐

  1. ?始終在finally塊中釋放鎖?:

    確保鎖一定會(huì)被釋放,避免死鎖:

    lock.lock();
    try {
        // 臨界區(qū)代碼
    } finally {
        lock.unlock();
    }
    
  2. ?避免嵌套鎖?:

    盡量不要在持有一個(gè)鎖的情況下嘗試獲取另一個(gè)鎖,容易導(dǎo)致死鎖。

  3. ?合理選擇鎖策略?:

    • 高吞吐場(chǎng)景:非公平鎖(默認(rèn))
    • 避免饑餓場(chǎng)景:公平鎖
  4. ?優(yōu)先使用tryLock?:

    特別是涉及多個(gè)鎖的操作,使用tryLock可以避免死鎖。

  5. ?合理使用Condition?:

    替代Object的wait/notify,實(shí)現(xiàn)更精準(zhǔn)的線程通信。

  6. ?性能考量?:

    簡(jiǎn)單同步場(chǎng)景優(yōu)先選擇synchronized,復(fù)雜場(chǎng)景才使用ReentrantLock。

總結(jié)

ReentrantLock作為Java并發(fā)編程中的重要工具,通過(guò)其可重入性、公平性選擇、靈活的鎖獲取方式和條件變量支持,為開發(fā)者提供了比synchronized更強(qiáng)大的線程同步能力。理解其基于AQS的實(shí)現(xiàn)原理,掌握各種高級(jí)特性的使用方法,并遵循最佳實(shí)踐,可以幫助我們構(gòu)建更高效、更健壯的并發(fā)程序。在實(shí)際開發(fā)中,應(yīng)根據(jù)具體場(chǎng)景需求,在synchronized和ReentrantLock之間做出合理選擇。

到此這篇關(guān)于Java ReentrantLock的使用與應(yīng)用實(shí)戰(zhàn)的文章就介紹到這了,更多相關(guān)Java ReentrantLock內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java中高效的對(duì)象映射庫(kù)Orika的用法詳解

    Java中高效的對(duì)象映射庫(kù)Orika的用法詳解

    Orika是一個(gè)高效的Java對(duì)象映射庫(kù),專門用于在Java應(yīng)用程序中簡(jiǎn)化對(duì)象之間的轉(zhuǎn)換,下面就跟隨小編一起來(lái)深入了解下Orika的具體使用吧
    2024-11-11
  • Java8 Stream Collectors收集器使用方法解析

    Java8 Stream Collectors收集器使用方法解析

    這篇文章主要介紹了Java8 Stream Collectors收集器使用方法解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-08-08
  • SpringBoot整合Netty服務(wù)端的實(shí)現(xiàn)示例

    SpringBoot整合Netty服務(wù)端的實(shí)現(xiàn)示例

    Netty提供了一套完整的API,用于處理網(wǎng)絡(luò)IO操作,如TCP和UDP套接字,本文主要介紹了SpringBoot整合Netty服務(wù)端的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-07-07
  • Java使用嵌套循環(huán)模擬ATM機(jī)取款業(yè)務(wù)操作示例

    Java使用嵌套循環(huán)模擬ATM機(jī)取款業(yè)務(wù)操作示例

    這篇文章主要介紹了Java使用嵌套循環(huán)模擬ATM機(jī)取款業(yè)務(wù)操作,結(jié)合實(shí)例形式分析了Java模擬ATM機(jī)取款業(yè)務(wù)操作的相關(guān)流程控制、數(shù)值判斷等操作技巧,需要的朋友可以參考下
    2019-11-11
  • 聊聊Spring data jpa @query使用原生SQl,需要注意的坑

    聊聊Spring data jpa @query使用原生SQl,需要注意的坑

    這篇文章主要介紹了Spring data jpa@query使用原生SQl,需要注意的坑,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Java中的ArrayList容量及擴(kuò)容方式

    Java中的ArrayList容量及擴(kuò)容方式

    這篇文章主要介紹了Java中的ArrayList容量及擴(kuò)容方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • druid?return行為方法源碼示例解析

    druid?return行為方法源碼示例解析

    這篇文章主要為大家介紹了druid?return行為源碼示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09
  • Java詳解swagger2如何配置使用

    Java詳解swagger2如何配置使用

    編寫和維護(hù)接口文檔是每個(gè)程序員的職責(zé),根據(jù)Swagger2可以快速幫助我們編寫最新的API接口文檔,再也不用擔(dān)心開會(huì)前仍忙于整理各種資料了,間接提升了團(tuán)隊(duì)開發(fā)的溝通效率
    2022-06-06
  • Java中四種訪問(wèn)控制權(quán)限解析(private、default、protected、public)

    Java中四種訪問(wèn)控制權(quán)限解析(private、default、protected、public)

    java當(dāng)中有4種訪問(wèn)修飾限定符privat、default(默認(rèn)訪問(wèn)權(quán)限),protected以及public,本文就詳細(xì)的介紹一下這四種方法的具體使用,感興趣的可以了解一下
    2023-05-05
  • Jmail發(fā)送郵件工具類分享

    Jmail發(fā)送郵件工具類分享

    這篇文章主要為大家分享了Jmail發(fā)送郵件工具類,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-06-06

最新評(píng)論