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

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

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

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

ReentrantLock概述與基本特性

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

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

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

ReentrantLock核心方法與使用

基礎(chǔ)鎖操作

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

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

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

高級鎖獲取方式

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

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

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

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

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

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

    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òu)建鎖和同步器的框架。AQS內(nèi)部維護(hù)了:

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

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

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

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

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

    新請求的線程可以直接插隊(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. ?加鎖過程?:

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

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

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)帶超時的轉(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);
    }
}

通過tryLock和超時機(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í)行可能長時間運(yùn)行的任務(wù)
            while (!Thread.currentThread().isInterrupted()) {
                // 任務(wù)邏輯...
            }
        } finally {
            lock.unlock();
        }
    }
}

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

ReentrantLock與synchronized的對比

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

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

ReentrantLock最佳實(shí)踐

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

    確保鎖一定會被釋放,避免死鎖:

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

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

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

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

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

  5. ?合理使用Condition?:

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

  6. ?性能考量?:

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

總結(jié)

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

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

相關(guān)文章

  • Servlet與JSP間的兩種傳值情況

    Servlet與JSP間的兩種傳值情況

    Servlet與JSP 之間的傳值有兩種情況:JSP -> Servlet, Servlet -> JSP,需要的朋友可以了解下
    2012-12-12
  • Java接口統(tǒng)一樣式返回模板的實(shí)現(xiàn)

    Java接口統(tǒng)一樣式返回模板的實(shí)現(xiàn)

    這篇文章主要介紹了Java接口統(tǒng)一樣式返回模板的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • java servlet結(jié)合Oracle搭建java的web開發(fā)環(huán)境

    java servlet結(jié)合Oracle搭建java的web開發(fā)環(huán)境

    今天我將與大家分享一下我學(xué)JAVA WEB寫的一些小實(shí)例 ,我個人是不太喜歡書本上的晦澀的概念的,所以我花了更多的時間在一些應(yīng)用實(shí)例上,我覺得這樣的學(xué)習(xí)方式很適合我,由簡到繁,由淺入深
    2015-12-12
  • 利用Java反射機(jī)制實(shí)現(xiàn)對象相同字段的復(fù)制操作

    利用Java反射機(jī)制實(shí)現(xiàn)對象相同字段的復(fù)制操作

    這篇文章主要介紹了利用Java反射機(jī)制實(shí)現(xiàn)對象相同字段的復(fù)制操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • 在maven中引入本地jar包的步驟

    在maven中引入本地jar包的步驟

    這篇文章主要介紹了在maven中引入本地jar包的步驟,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下
    2021-04-04
  • SpringBoot請求與響應(yīng)實(shí)例全解析

    SpringBoot請求與響應(yīng)實(shí)例全解析

    文章主要介紹了SpringBoot中請求與響應(yīng)的處理方式,包括簡單參數(shù)、實(shí)體參數(shù)、數(shù)組集合參數(shù)、日期參數(shù)、JSON參數(shù)和路徑參數(shù)的處理,同時,還介紹了響應(yīng)的處理,包括@ResponseBody注解和統(tǒng)一響應(yīng)結(jié)果類的設(shè)計(jì)
    2026-04-04
  • java時區(qū)時間轉(zhuǎn)為UTC的代碼示例和詳細(xì)解釋

    java時區(qū)時間轉(zhuǎn)為UTC的代碼示例和詳細(xì)解釋

    作為一名經(jīng)驗(yàn)豐富的開發(fā)者,我經(jīng)常被問到如何將Java中的時間轉(zhuǎn)換為UTC時間,這篇文章主要介紹了java時區(qū)時間轉(zhuǎn)為UTC的代碼示例和詳細(xì)解釋,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-09-09
  • Java常見面試題之final在java中的作用是什么

    Java常見面試題之final在java中的作用是什么

    這篇文章主要介紹了Java常見面試題之final在java中的作用是什么,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-01-01
  • mybatis-plus?Wrapper條件構(gòu)造器updateForSet更新方式

    mybatis-plus?Wrapper條件構(gòu)造器updateForSet更新方式

    這篇文章主要介紹了mybatis-plus?Wrapper條件構(gòu)造器updateForSet更新方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • MyBatis 自動更新時間的方法實(shí)現(xiàn)

    MyBatis 自動更新時間的方法實(shí)現(xiàn)

    本文主要介紹了MyBatis 自動更新時間的方法實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-06-06

最新評論

永吉县| 邵东县| 汽车| 六安市| 云安县| 盘山县| 北安市| 读书| 西充县| 兴业县| 涪陵区| 新晃| 阳西县| 舒兰市| 绥江县| 镇平县| 赤水市| 黄山市| 清水县| 洪湖市| 隆林| 深州市| 绥棱县| 扶绥县| 彰化县| 新营市| 彰武县| 依安县| 同江市| 顺义区| 吉木乃县| 汉川市| 虞城县| 莒南县| 左云县| 苗栗县| 凌云县| 诸城市| 黑龙江省| 镇赉县| 葵青区|