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

java面試JDK8?new?ReentrantLock()加鎖流程解析

 更新時間:2023年07月06日 10:27:12   作者:子瞻  
這篇文章主要為大家介紹了java面試JDK8?new?ReentrantLock()加鎖流程解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

new ReentrantLock() 加鎖流程

//默認執(zhí)行NonfairSync.lock();
final void lock() {
            //cas 0 -> 1 ,如果操作成功,將當前線程設(shè)置為獨占線程
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
                //如果操作失敗
                acquire(1);
        }
public final void acquire(int arg) {
        //tryAcquire(arg)嘗試獲取鎖,如果獲取鎖失敗返回false,否則返回true
        if (!tryAcquire(arg) &&
            //嘗試獲得鎖,如果當前線程被中斷 返回 true,否則返回false
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            //獲得鎖失敗,且當前線程的中斷狀態(tài)為true,則重新去嘗試
            selfInterrupt();
    }

tryAcquire()

tryAcquire()最終默認調(diào)用ReentrantLock.NonfairSync.nonfairTryAcquire();

final boolean nonfairTryAcquire(int acquires) {
            //獲取當前線程
            final Thread current = Thread.currentThread();
            //獲取state值
            int c = getState();
            //0 代表沒有線程占用鎖
            if (c == 0) {
                //cas 將 0 改為 1
                if (compareAndSetState(0, acquires)) {
                    //cas 成功之后 將獨占線程改為當前線程
                    setExclusiveOwnerThread(current);
                    //返回成功
                    return true;
                }
            }
            //如果有線程獲取當前線程(也就是當前線程是獨占線程)
            else if (current == getExclusiveOwnerThread()) {
                //state值加1
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                //保存新的state值
                setState(nextc);
                //返回true
                return true;
            }
            //否則,就返回false
            return false;
        }

AbstractQueuedSynchronizer.addWaiter(Node.EXCLUSIVE)

解析

private Node addWaiter(Node mode) {
        Node node = new Node(Thread.currentThread(), mode);
        //尾節(jié)點賦值給pred;
        Node pred = tail;
        //尾節(jié)點不為空
        if (pred != null) {
            //當前的節(jié)點prev指針指向現(xiàn)在的尾節(jié)點
            node.prev = pred;
            //cas 將當前尾節(jié)點 替換為 node節(jié)點
            if (compareAndSetTail(pred, node)) {
                //當前尾節(jié)點的next指針指向 node節(jié)點
                pred.next = node;
                return node;
            }
        }
        //如果尾節(jié)點為空或者cas替換失敗,則執(zhí)行入隊操作
        enq(node);
        return node;
    }
    //入隊操作:將當前節(jié)點設(shè)置為尾節(jié)點,并更新當前節(jié)點和替換前的尾節(jié)點的指針指向
    private Node enq(final Node node) {
            for (;;) {
                //把尾節(jié)點賦值給一個變量
                Node t = tail;
                //如果尾節(jié)點為空
                if (t == null) {
                    //新建一個節(jié)點,設(shè)置為頭節(jié)點
                    if (compareAndSetHead(new Node()))
                        //把頭節(jié)點賦值尾節(jié)點
                        tail = head;
                } else {
                    //如果尾節(jié)點不為空,當前節(jié)點的prev指針指向尾節(jié)點
                    node.prev = t;
                    //cas 將當前節(jié)點設(shè)置為尾節(jié)點
                    if (compareAndSetTail(t, node)) {
                        //替換前的尾節(jié)點的next指針指向當前節(jié)點
                        t.next = node;
                        return t;
                    }
                }
                //如果cas 替換尾節(jié)點 失敗,則循環(huán)執(zhí)行,直到成功為止
            }
      }

AbstractQueuedSynchronizer.acquireQueued(addWaiter(Node.EXCLUSIVE), arg);

//已經(jīng)入隊的非中斷線程再次嘗試獲取鎖
final boolean acquireQueued(final Node node, int arg) {
        boolean failed = true;
        try {
            boolean interrupted = false;
            for (;;) {
                //獲取當前節(jié)點的前一個節(jié)點信息
                final Node p = node.predecessor();
                //如果前一個節(jié)點信息為頭節(jié)點,并且成功獲得鎖
                if (p == head && tryAcquire(arg)) {
                    //設(shè)置當前節(jié)點為頭節(jié)點
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    //返回當前節(jié)點的線程中斷狀態(tài)
                    return interrupted;
                }
                //如果當前節(jié)點的前驅(qū)節(jié)點不是頭節(jié)點 或者 獲得鎖失敗,則阻塞當前節(jié)點線程等待當前節(jié)點的線程被喚醒,并判斷中斷狀態(tài)
                if (shouldParkAfterFailedAcquire(p, node) &&
                    //阻塞當前線程,等待當前線程被喚醒后,判斷當前線程的中斷狀態(tài)
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

shouldParkAfterFailedAcquire(p, node)

細節(jié)如下:

//獲取鎖失敗的線程檢查并更新node中的waitStatus。如果線程應該被阻塞返回true。
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
        //獲取前一個節(jié)點的等待狀態(tài)
        int ws = pred.waitStatus;
        //-1,代表前一個節(jié)點被阻塞中,需要喚醒
        if (ws == Node.SIGNAL)
            return true;
        if (ws > 0) {
            // > 0 代表前一個節(jié)點被取消,就遞歸往找waitStatus > 0的節(jié)點信息
            do {
                node.prev = pred = pred.prev;
            } while (pred.waitStatus > 0);
            //找到后,將此節(jié)點的next指針指向當前節(jié)點
            pred.next = node;
        } else {
            /*
             * waitStatus must be 0 or PROPAGATE.  Indicate that we
             * need a signal, but don't park yet.  Caller will need to
             * retry to make sure it cannot acquire before parking.
             * waitStatus 必須是0 或者 -3(表示可以共享獲得)。表明我們需要喚醒,但是還沒有阻塞。調(diào)用者需要重試去保證在阻塞操作之前不能獲取成功
             */
            //cas 將 前一個節(jié)點的waitStatus 改為 -1(需要喚醒)
            compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
        }
        //返回false
        return false;
    }
    private final boolean parkAndCheckInterrupt() {
        //阻塞當前線程
        LockSupport.park(this);
        //當前線程被喚醒后,判斷當前線程的的中斷狀態(tài)
        //這里有一個非常重要的知識點:喚醒阻塞線程的方式 1.unpark 2.interrupt
        return Thread.interrupted();
    }

以上就是java面試JDK8 new ReentrantLock()加鎖流程解析的詳細內(nèi)容,更多關(guān)于java JDK8 new ReentrantLock的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Idea2020.2創(chuàng)建JavaWeb項目(部署Tomcat)方法詳解

    Idea2020.2創(chuàng)建JavaWeb項目(部署Tomcat)方法詳解

    這篇文章主要介紹了Idea2020.2創(chuàng)建JavaWeb項目(部署Tomcat)方法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-08-08
  • Java實現(xiàn)拖拽文件上傳dropzone.js的簡單使用示例代碼

    Java實現(xiàn)拖拽文件上傳dropzone.js的簡單使用示例代碼

    本篇文章主要介紹了Java實現(xiàn)拖拽文件上傳dropzone.js的簡單使用示例代碼,具有一定的參考價值,有興趣的可以了解一下
    2017-07-07
  • 淺談Java并發(fā)編程之synchronized有序性誤區(qū)

    淺談Java并發(fā)編程之synchronized有序性誤區(qū)

    本文主要介紹了淺談Java并發(fā)編程之synchronized有序性誤區(qū),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2026-02-02
  • 淺談java中String StringBuffer StringBuilder的區(qū)別

    淺談java中String StringBuffer StringBuilder的區(qū)別

    下面小編就為大家?guī)硪黄獪\談java中String StringBuffer StringBuilder的區(qū)別。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-06-06
  • 深入理解java.lang.String類的不可變性

    深入理解java.lang.String類的不可變性

    不可變類只是其實例不能被修改的類。每個實例中包含的所有信息都必須在創(chuàng)建該實例的時候就提供,并且在對象的整個生命周期內(nèi)固定不變,感興趣的可以了解一下
    2021-06-06
  • Struts2 $,#,%詳解及實例代碼

    Struts2 $,#,%詳解及實例代碼

    這篇文章主要介紹了Struts2 $,#,%詳解及實例代碼的相關(guān)資料,需要的朋友可以參考下
    2016-12-12
  • Java字符流和字節(jié)流對文件操作的區(qū)別

    Java字符流和字節(jié)流對文件操作的區(qū)別

    本篇文章主要介紹了Java的IO流分為字符流(Reader,Writer)和字節(jié)流(InputStream,OutputStream),字節(jié)流顧名思義字節(jié)流就是將文件的內(nèi)容讀取到字節(jié)數(shù)組,對初學者很有用,有需要的朋友可以了解一下。
    2016-10-10
  • 基于Java制作一個好玩的打飛機游戲

    基于Java制作一個好玩的打飛機游戲

    這篇文章主要介紹了基于Java制作的打飛機小游戲,這里整理了詳細的代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • redisson分布式限流RRateLimiter源碼解析

    redisson分布式限流RRateLimiter源碼解析

    這篇文章主要為大家介紹了redisson分布式限流RRateLimiter源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-11-11
  • java中如何使用HttpClient調(diào)用接口

    java中如何使用HttpClient調(diào)用接口

    這篇文章主要介紹了java中如何使用HttpClient調(diào)用接口,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-10-10

最新評論

土默特左旗| 巴彦淖尔市| 万载县| 阳泉市| 甘肃省| 德阳市| 阿合奇县| 台山市| 荆门市| 缙云县| 东山县| 大丰市| 乐陵市| 台中县| 运城市| 石首市| 沛县| 夏河县| 湛江市| 淳化县| 麦盖提县| 台北市| 运城市| 咸丰县| 台南县| 铜陵市| 长治县| 井冈山市| 沽源县| 建阳市| 桐乡市| 洛川县| 吉安市| 白河县| 定边县| 新竹县| 巴马| 河南省| 大洼县| 灌南县| 全南县|