欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java ReentrantLock的使用與應用實戰(zhàn)

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

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

ReentrantLock概述與基本特性

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

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

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

ReentrantLock核心方法與使用

基礎鎖操作

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

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

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

高級鎖獲取方式

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

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

    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)??:

    允許在等待鎖的過程中響應中斷信號:

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

鎖狀態(tài)查詢

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

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

ReentrantLock實現(xiàn)原理

AQS框架基礎

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

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

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

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

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

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

    新請求的線程可以直接插隊嘗試獲取鎖,不考慮等待隊列

  2. ?公平鎖?:

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

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

鎖的獲取與釋放流程

  1. ?加鎖過程?:

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

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

ReentrantLock實戰(zhàn)應用

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

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

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();
        }
    }
}

這種實現(xiàn)比synchronized+wait/notify更高效,因為可以精準喚醒生產(chǎn)者或消費者線程。

銀行轉賬避免死鎖

使用tryLock實現(xià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和超時機制,有效預防了死鎖風險。

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

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

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

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

ReentrantLock與synchronized的對比

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

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

ReentrantLock最佳實踐

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

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

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

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

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

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

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

  5. ?合理使用Condition?:

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

  6. ?性能考量?:

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

總結

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

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

相關文章

  • Java中高效的對象映射庫Orika的用法詳解

    Java中高效的對象映射庫Orika的用法詳解

    Orika是一個高效的Java對象映射庫,專門用于在Java應用程序中簡化對象之間的轉換,下面就跟隨小編一起來深入了解下Orika的具體使用吧
    2024-11-11
  • Java8 Stream Collectors收集器使用方法解析

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

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

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

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

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

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

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

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

    Java中的ArrayList容量及擴容方式

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

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

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

    Java詳解swagger2如何配置使用

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

    Java中四種訪問控制權限解析(private、default、protected、public)

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

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

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

最新評論