<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          ReentrantLock可重入鎖、公平鎖非公平鎖區(qū)別與實(shí)現(xiàn)原理

          共 1677字,需瀏覽 4分鐘

           ·

          2021-10-22 12:30

          點(diǎn)擊上方藍(lán)色字體,選擇“標(biāo)星公眾號(hào)”

          優(yōu)質(zhì)文章,第一時(shí)間送達(dá)

          ReentrantLock是lock接口的一個(gè)實(shí)現(xiàn)類,里面實(shí)現(xiàn)了可重入鎖和公平鎖非公平鎖

          ReentrantLock公平鎖和不公平鎖實(shí)現(xiàn)原理

          公平鎖會(huì)獲取鎖時(shí)會(huì)判斷阻塞隊(duì)列里是否有線程再等待,若有獲取鎖就會(huì)失敗,并且會(huì)加入阻塞隊(duì)列

          非公平鎖獲取鎖時(shí)不會(huì)判斷阻塞隊(duì)列是否有線程再等待,所以對(duì)于已經(jīng)在等待的線程來(lái)說(shuō)是不公平的,但如果是因?yàn)槠渌驔](méi)有競(jìng)爭(zhēng)到鎖,它也會(huì)加入阻塞隊(duì)列

          進(jìn)入阻塞隊(duì)列的線程,競(jìng)爭(zhēng)鎖時(shí)都是公平的,應(yīng)為隊(duì)列為先進(jìn)先出(FIFO)

          默認(rèn)實(shí)現(xiàn)的是非公平鎖

          public?ReentrantLock()?{
          ????//非公平鎖
          ????sync?=?new?NonfairSync();
          }

          還提供了另外一種方式,可傳入一個(gè)boolean值,true時(shí)為公平鎖,false時(shí)為非公平鎖

          //公平鎖
          public?ReentrantLock(boolean?fair)?{
          ????sync?=?fair???new?FairSync()?:?new?NonfairSync();
          }

          非公平鎖

          非公平鎖獲取鎖nonfairTryAcquire方法,對(duì)鎖狀態(tài)進(jìn)行了判斷,并沒(méi)有把鎖加入同步隊(duì)列中

          ????static?final?class?NonfairSync?extends?Sync?{
          ????????private?static?final?long?serialVersionUID?=?7316153563782823691L;

          ????????final?void?lock()?{
          ????????????//比較當(dāng)前狀態(tài)?如果持有者是當(dāng)前線程
          ????????????if?(compareAndSetState(0,?1))
          ????????????????setExclusiveOwnerThread(Thread.currentThread());
          ????????????else
          ????????????????//如果不是?嘗試獲取鎖
          ????????????????acquire(1);
          ????????}

          ????????protected?final?boolean?tryAcquire(int?acquires)?{
          ????????????//獲取鎖
          ????????????return?nonfairTryAcquire(acquires);
          ????????}
          ????}

          final?boolean?nonfairTryAcquire(int?acquires)?{
          ????????????final?Thread?current?=?Thread.currentThread();
          ????????????int?c?=?getState();
          ????????????//判斷當(dāng)前對(duì)象是否被持有
          ????????????if?(c?==?0)?{
          ????????????????//沒(méi)有持有就直接改變狀態(tài)持有鎖
          ????????????????if?(compareAndSetState(0,?acquires))?{
          ????????????????????setExclusiveOwnerThread(current);
          ????????????????????return?true;
          ????????????????}
          ????????????}
          ?????????//若被持有?判斷鎖是否是當(dāng)前線程??也是可重入鎖的關(guān)鍵代碼
          ????????????else?if?(current?==?getExclusiveOwnerThread())?{
          ????????????????int?nextc?=?c?+?acquires;
          ????????????????if?(nextc?????????????????????throw?new?Error("Maximum?lock?count?exceeded");
          ????????????????setState(nextc);
          ????????????????return?true;
          ????????????}
          ????????????return?false;
          ????????}

          公平鎖

          代碼和nonfairTryAcquire唯一的不同在于增加了hasQueuedPredecessors方法的判斷

          static?final?class?FairSync?extends?Sync?{
          ????????private?static?final?long?serialVersionUID?=?-3000897897090466540L;

          ???????protected?final?boolean?tryAcquire(int?acquires)?{
          ???????????//獲取當(dāng)前線程
          ????????????final?Thread?current?=?Thread.currentThread();
          ????????????int?c?=?getState();
          ????????????//判斷當(dāng)前對(duì)象是否被持有
          ????????????if?(c?==?0)?{
          ????????????????//如果等待隊(duì)列為空?并且使用CAS獲取鎖成功???否則返回false然后從隊(duì)列中獲取節(jié)點(diǎn)
          ????????????????if?(!hasQueuedPredecessors()?&&compareAndSetState(0,?acquires))?{
          ????????????????????//把當(dāng)前線程持有
          ????????????????????setExclusiveOwnerThread(current);
          ????????????????????return?true;
          ????????????????}
          ????????????}
          ???????????//若被持有?判斷鎖是否是當(dāng)前線程??可重入鎖的關(guān)鍵代碼
          ????????????else?if?(current?==?getExclusiveOwnerThread())?{
          ????????????????//計(jì)數(shù)加1?返回
          ????????????????int?nextc?=?c?+?acquires;
          ????????????????if?(nextc?????????????????????throw?new?Error("Maximum?lock?count?exceeded");
          ????????????????setState(nextc);
          ????????????????return?true;
          ????????????}
          ????????????//不是當(dāng)前線程持有?執(zhí)行
          ????????????return?false;
          ????????}
          ????}

          acquire()獲取鎖

          ????public?final?void?acquire(int?arg)?{
          ????????//如果當(dāng)前線程嘗試獲取鎖失敗并且?加入把當(dāng)前線程加入了等待隊(duì)列?
          ????????if?(!tryAcquire(arg)?&&acquireQueued(addWaiter(Node.EXCLUSIVE),?arg))
          ????????????//先中斷當(dāng)前線程
          ????????????selfInterrupt();
          ????}

          關(guān)鍵代碼

          就是tryAcquire方法中hasQueuedPredecessors判斷隊(duì)列是否有其他節(jié)點(diǎn)

          public?final?boolean?hasQueuedPredecessors()?{
          ????Node?t?=?tail;?//?Read?fields?in?reverse?initialization?order
          ????Node?h?=?head;
          ????Node?s;
          ????return?h?!=?t?&&
          ????????((s?=?h.next)?==?null?||?s.thread?!=?Thread.currentThread());
          }

          可重入性實(shí)現(xiàn)原理

          在線程獲取鎖的時(shí)候,如果已經(jīng)獲取鎖的線程是當(dāng)前線程的話則直接再次獲取成功

          由于鎖會(huì)被獲取n次,那么只有鎖在被釋放同樣的n次之后,該鎖才算是完全釋放成功

          1、獲取鎖方法

          ?protected?final?boolean?tryAcquire(int?acquires)?{
          ???????????//獲取當(dāng)前線程
          ????????????final?Thread?current?=?Thread.currentThread();
          ????????????int?c?=?getState();
          ????????????//判斷當(dāng)前對(duì)象是否被持有
          ????????????if?(c?==?0)?{
          ??????????????//...略
          ????????????}
          ???????????//若被持有?判斷鎖是否是當(dāng)前線程??可重入鎖的關(guān)鍵代碼
          ????????????else?if?(current?==?getExclusiveOwnerThread())?{
          ????????????????//計(jì)數(shù)加1?返回
          ????????????????int?nextc?=?c?+?acquires;
          ????????????????if?(nextc?????????????????????throw?new?Error("Maximum?lock?count?exceeded");
          ????????????????setState(nextc);
          ????????????????return?true;
          ????????????}
          ????????????//不是當(dāng)前線程持有?執(zhí)行
          ????????????return?false;
          ????????}

          每次如果獲取到的都是當(dāng)前線程這里都會(huì)計(jì)數(shù)加1

          釋放鎖

          protected?final?boolean?tryRelease(int?releases)?{
          ????//每次釋放都減1
          ????int?c?=?getState()?-?releases;
          ????if?(Thread.currentThread()?!=?getExclusiveOwnerThread())
          ????????throw?new?IllegalMonitorStateException();
          ????boolean?free?=?false;
          ????//等于0才釋放鎖成功
          ????if?(c?==?0)?{
          ????????free?=?true;
          ????????setExclusiveOwnerThread(null);
          ????}
          ????setState(c);
          ????return?free;
          }

          如果鎖被獲取n次,也要釋放了n次,只有完全釋放才會(huì)返回false


          ? 作者?|??cg-ww

          來(lái)源 |??cnblogs.com/cg-ww/p/15422013.html


          加鋒哥微信:?java1239??
          圍觀鋒哥朋友圈,每天推送Java干貨!

          瀏覽 43
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美视频一区二区三区四区 | 午夜成人免费网站 | 女女性爱视频 | 亚欧精品久久久久久久久久 | 91大神无码 |