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

深入剖析Java ReentrantLock的源碼

 更新時間:2022年11月18日 16:39:47   作者:一燈架構  
ReentrantLock和Synchronized都是Java開發(fā)中最常用的鎖,與Synchronized這種JVM內置鎖不同的是,ReentrantLock提供了更豐富的語義。本文就來深入剖析一下ReentrantLock源碼,需要的可以參考一下

ReentrantLock和Synchronized都是Java開發(fā)中最常用的鎖,與Synchronized這種JVM內置鎖不同的是,ReentrantLock提供了更豐富的語義??梢詣?chuàng)建公平鎖或非公平鎖、響應中斷、超時等待、按條件喚醒等。在某些場景下,使用ReentrantLock更適合,功能更強大。

前兩篇文章,我們分析了AQS的加鎖流程、以及源碼實現(xiàn)。當時我們就說了,AQS使用了模板設計模式,父類中定義加鎖流程,子類去實現(xiàn)具體的加鎖邏輯。所以大部分加鎖代碼已經在父類AQS中實現(xiàn)了,導致ReentrantLock的源碼非常簡單,一塊學習一下。

先看一下ReentrantLock怎么使用?

1. ReentrantLock的使用

/**
 * @author 一燈架構
 * @apiNote ReentrantLock示例
 **/
public class ReentrantLockDemo {
    
    public static void main(String[] args) {
        // 1. 創(chuàng)建ReentrantLock對象
        ReentrantLock lock = new ReentrantLock();
        // 2. 加鎖
        lock.lock();
        try {
            // 3. 這里執(zhí)行具體的業(yè)務邏輯
        } finally {
            // 4. 釋放鎖
            lock.unlock();
        }
    }
}

可以看到ReentrantLock的使用非常簡單,調用lock加鎖,unlock釋放鎖,需要配置try/finally使用,保證在代碼執(zhí)行出錯的時候也能釋放鎖。

ReentrantLock也可以配合Condition條件使用,具體可以翻一下前幾篇文章中BlockingQueue的源碼解析,那里面有ReentrantLock的實際使用。

再看一下ReentrantLock的類結構

2. ReentrantLock類結構

// 實現(xiàn)Lock接口
public class ReentrantLock implements Lock {

    // 只有一個Sync同步變量
    private final Sync sync;

    // Sync繼承自AQS,主要邏輯都在這里面
    abstract static class Sync extends AbstractQueuedSynchronizer {
    }

    // Sync的兩個子類,分別實現(xiàn)了公平鎖和非公平鎖
    static final class FairSync extends Sync {
    }
    static final class NonfairSync extends Sync {
    }

}

可以看出ReentrantLock的類結構非常簡單,實現(xiàn)了Lock接口。

類里面有兩個靜態(tài)內部類,分別實現(xiàn)公平鎖和非公平鎖。

看一下Lock接口中,定義了哪些方法?

public interface Lock {

    // 加鎖
    void lock();

    // 加可中斷的鎖
    void lockInterruptibly() throws InterruptedException;

    // 嘗試加鎖
    boolean tryLock();

    // 一段時間內,嘗試加鎖
    boolean tryLock(long time, TimeUnit unit) throws InterruptedException;

    // 釋放鎖
    void unlock();

    // 新建條件狀態(tài)
    Condition newCondition();
}

就是一些使用鎖的常用方法。

在上篇文章中瀏覽AQS源碼的時候,了解到AQS定義了一些有關具體加鎖、釋放鎖的抽象方法,留給子類去實現(xiàn),再看一下有哪些抽象方法:

// 加獨占鎖
protected boolean tryAcquire(int arg) {
    throw new UnsupportedOperationException();
}
// 釋放獨占鎖
protected boolean tryRelease(int arg) {
    throw new UnsupportedOperationException();
}

// 加共享鎖
protected int tryAcquireShared(int arg) {
    throw new UnsupportedOperationException();
}
// 釋放共享鎖
protected boolean tryReleaseShared(int arg) {
    throw new UnsupportedOperationException();
}

// 判斷是否是當前線程正在持有鎖
protected boolean isHeldExclusively() {
    throw new UnsupportedOperationException();
}

由于ReentrantLock使用的是獨占鎖,所以只需要實現(xiàn)獨占鎖相關的方法就可以了。

3. ReentrantLock源碼解析

3.1 ReentrantLock構造方法

// 默認的構造方法,使用非公平鎖
public ReentrantLock() {
    sync = new NonfairSync();
}

// 傳true,可以指定使用公平鎖
public ReentrantLock(boolean fair) {
    sync = fair ? new FairSync() : new NonfairSync();
}

在創(chuàng)建ReentrantLock對象的時候,可以指定使用公平鎖還是非公平鎖,默認使用非公平鎖,顯然非公平鎖的性能更好。

先思考一個面試??紗栴},公平鎖和非公平鎖是怎么實現(xiàn)的?

3.2 非公平鎖源碼

先看一下加鎖源碼:

從父類ReentrantLock的加鎖方法入口:

public class ReentrantLock implements Lock {
    // 加鎖入口方法
    public void lock() {
        // 調用Sync中加鎖方法
        sync.lock();
    }
}

在子類NonfairSync的加鎖方法:

// 非公平鎖
static final class NonfairSync extends Sync {

    // 加鎖
    final void lock() {
        // 1. 先嘗試加鎖(使用CAS設置state=1)
        if (compareAndSetState(0, 1))
            // 2. 加鎖成功,就把當前線程設置為持有鎖線程
            setExclusiveOwnerThread(Thread.currentThread());
        else
            // 3. 沒加鎖成功,再調用父類AQS中實際的加鎖邏輯
            acquire(1);
    }
}

加鎖邏輯也很簡單,先嘗試使用CAS加鎖(也就是把state從0設置成1),加鎖成功,就把當前線程設置為持有鎖線程。

設計者很聰明,在鎖競爭不激烈的情況下,很大概率可以加鎖成功,也就不用走else中復雜的加鎖邏輯了。

如果沒有加鎖成功,還是需要走else中調用父類AQS的acquire方法,而acquire又需要調用子類的tryAcquire方法。

調用鏈路就是下面這樣:

根據(jù)調用鏈路,實際的加鎖邏輯在Sync.nonfairTryAcquire方法里面。

abstract static class Sync extends AbstractQueuedSynchronizer {
    // 非公平鎖的最終加鎖方法
    final boolean nonfairTryAcquire(int acquires) {
        final Thread current = Thread.currentThread();
        // 1. 獲取同步狀態(tài)
        int c = getState();
        // 2. state=0表示無鎖,先嘗試加鎖(使用CAS設置state=1)
        if (c == 0) {
            if (compareAndSetState(0, acquires)) {
                // 3. 加鎖成功,就把當前線程設置為持有鎖線程
                setExclusiveOwnerThread(current);
                return true;
            }
            // 4. 如果當前線程已經持有鎖,執(zhí)行可重入的邏輯
        } else if (current == getExclusiveOwnerThread()) {
            // 5. 加鎖次數(shù)+acquires
            int nextc = c + acquires;
            // 6. 超過tnt類型最大值,溢出了
            if (nextc < 0)
                throw new Error("Maximum lock count exceeded");
            setState(nextc);
            return true;
        }
        return false;
    }
}

再看一下釋放鎖的調用流程,公平鎖和非公平鎖流程是一樣的,最終都是執(zhí)行Sync.tryRelease方法:

abstract static class Sync extends AbstractQueuedSynchronizer {
    // 釋放鎖
    protected final boolean tryRelease(int releases) {
        // 1. 同步狀態(tài)減去釋放鎖次數(shù)
        int c = getState() - releases;
        // 2. 校驗當前線程不持有鎖,就報錯
        if (Thread.currentThread() != getExclusiveOwnerThread())
            throw new IllegalMonitorStateException();
        boolean free = false;
        // 3. 判斷同步狀態(tài)是否等于0,無鎖后,就刪除持有鎖的線程
        if (c == 0) {
            free = true;
            setExclusiveOwnerThread(null);
        }
        setState(c);
        return free;
    }
}

再看一下公平鎖的源碼

3.3 公平鎖源碼

先看一下公平鎖的加鎖流程:

最終的加鎖方法是FairSync.tryAcquire,看一下具體邏輯:

static final class FairSync extends Sync {

    // 實現(xiàn)父類的加鎖邏輯
    protected final boolean tryAcquire(int acquires) {
        final Thread current = Thread.currentThread();
        // 1. 獲取同步狀態(tài)
        int c = getState();
        // 2. state=0表示無鎖,先嘗試加鎖(使用CAS設置state=1)
        if (c == 0) {
            // 3. 判斷當前線程是不是頭節(jié)點的下一個節(jié)點(講究先來后到)
            if (!hasQueuedPredecessors() &&
                    compareAndSetState(0, acquires)) {
                setExclusiveOwnerThread(current);
                return true;
            }
            // 4. 如果當前線程已經持有鎖,執(zhí)行可重入的邏輯
        } else if (current == getExclusiveOwnerThread()) {
            // 5. 加鎖次數(shù)+acquires
            int nextc = c + acquires;
            // 6. 超過tnt類型最大值,溢出了
            if (nextc < 0)
                throw new Error("Maximum lock count exceeded");
            setState(nextc);
            return true;
        }
        return false;
    }

    // 判斷當前線程是不是頭節(jié)點的下一個節(jié)點(講究先來后到)
    public final boolean hasQueuedPredecessors() {
        Node t = tail;
        Node h = head;
        Node s;
        return h != t &&
                ((s = h.next) == null || s.thread != Thread.currentThread());
    }
}

公平鎖的釋放鎖邏輯跟非公平鎖一樣,上面已經講過。

4. 總結

看完了ReentrantLock的所有源碼,是不是覺得ReentrantLock很簡單。

由于加鎖流程的編排工作已經在父類AQS中實現(xiàn),子類只需要實現(xiàn)具體的加鎖邏輯即可。

加鎖邏輯也很簡單,也就是修改同步狀態(tài)state的值和持有鎖的線程exclusiveOwnerThread。

到此這篇關于深入剖析Java ReentrantLock的源碼的文章就介紹到這了,更多相關Java ReentrantLock內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • java實現(xiàn)自動售貨機

    java實現(xiàn)自動售貨機

    這篇文章主要為大家詳細介紹了java實現(xiàn)自動售貨機,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • jmeter添加自定義擴展函數(shù)之圖片base64編碼示例詳解

    jmeter添加自定義擴展函數(shù)之圖片base64編碼示例詳解

    這篇文章主要介紹了jmeter添加自定義擴展函數(shù)之圖片base64編碼,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-01-01
  • Spring Boot配置Swagger的實現(xiàn)代碼

    Spring Boot配置Swagger的實現(xiàn)代碼

    這篇文章主要介紹了Spring Boot配置Swagger的實現(xiàn)代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-12-12
  • 詳解使用Spring的BeanPostProcessor優(yōu)雅的實現(xiàn)工廠模式

    詳解使用Spring的BeanPostProcessor優(yōu)雅的實現(xiàn)工廠模式

    這篇文章主要介紹了詳解使用Spring的BeanPostProcessor優(yōu)雅的實現(xiàn)工廠模式,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-07-07
  • Java多線程中的CountDownLatch詳細解讀

    Java多線程中的CountDownLatch詳細解讀

    這篇文章主要介紹了Java多線程中的CountDownLatch詳細解讀,一個同步輔助類,在完成一組正在其他線程中執(zhí)行的操作之前,它允許一個或多個線程一直等待,用給定的計數(shù) 初始化 CountDownLatch,需要的朋友可以參考下
    2023-11-11
  • Spring Aop組成部分及實現(xiàn)步驟

    Spring Aop組成部分及實現(xiàn)步驟

    面向切面編程,是對面向對象編程的一種補充,是一種編程思想,是對某一類的事情的集中處理,這篇文章主要介紹了Spring Aop組成部分及實現(xiàn)步驟,需要的朋友可以參考下
    2023-08-08
  • SpringCloud-Alibaba-Nacos啟動失敗解決方案

    SpringCloud-Alibaba-Nacos啟動失敗解決方案

    這篇文章主要介紹了SpringCloud-Alibaba-Nacos啟動失敗解決方案,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-04-04
  • 詳解SpringMVC組件之HandlerMapping(二)

    詳解SpringMVC組件之HandlerMapping(二)

    這篇文章主要介紹了詳解SpringMVC組件之HandlerMapping(二),HandlerMapping組件是Spring?MVC核心組件,用來根據(jù)請求的request查找對應的Handler,在Spring?MVC中,有各式各樣的Web請求,每個請求都需要一個對應的Handler來處理,需要的朋友可以參考下
    2023-08-08
  • 史上最全面的Spring Boot配置文件深入講解

    史上最全面的Spring Boot配置文件深入講解

    Springboot極大的簡化了Spring框架的使用配置流程,在核心配置文件里,幾乎可以完成所有的配置工作,下面這篇文章主要給大家介紹了關于Spring Boot配置文件的相關資料,文中介紹的非常全面,需要的朋友可以參考下
    2018-12-12
  • idea切換分支的時候,忽略一些無用的修改設置

    idea切換分支的時候,忽略一些無用的修改設置

    這篇文章主要介紹了idea切換分支的時候,忽略一些無用的修改操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02

最新評論

绥棱县| 巴里| 天峻县| 竹北市| 元谋县| 康保县| 屏山县| 县级市| 通榆县| 镇远县| 湘阴县| 东至县| 友谊县| 邢台县| 宁南县| 晋州市| 茶陵县| 青浦区| 成武县| 缙云县| 昌黎县| 道真| 景谷| 山丹县| 佛山市| 兴化市| 昌乐县| 马鞍山市| 迁西县| 全州县| 孟州市| 甘洛县| 桑日县| 庆元县| 罗田县| 霞浦县| 沂源县| 清水县| 巧家县| 卢湾区| 萨迦县|