<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>

          Redisson 分布式鎖源碼 06:公平鎖排隊(duì)加鎖

          共 1452字,需瀏覽 3分鐘

           ·

          2021-07-01 22:47

          前言

          在上一篇文章中已經(jīng)分析過公平鎖的加鎖源碼,并得出結(jié)論:

          1. Redis Hash 數(shù)據(jù)結(jié)構(gòu):存放當(dāng)前鎖,Redis Key 就是鎖,Hash 的 field 是加鎖線程,Hash 的 value 是 重入次數(shù);
          2. Redis List 數(shù)據(jù)結(jié)構(gòu):充當(dāng)線程等待隊(duì)列,新的等待線程會(huì)使用 rpush 命令放在隊(duì)列右邊;
          3. Redis sorted set 有序集合數(shù)據(jù)結(jié)構(gòu):存放等待線程的順序,分?jǐn)?shù) score 用來是等待線程的超時(shí)時(shí)間戳。

          現(xiàn)在看一下加鎖失敗被放到等待隊(duì)列之后,線程是如何處理的?

          1

          排隊(duì)等鎖

          源碼入口:org.redisson.RedissonLock#lock(long, java.util.concurrent.TimeUnit, boolean)

          線程進(jìn)入排隊(duì)之后,在 Java 代碼中會(huì) while (true) 一直循環(huán)調(diào)用 tryAcquire,嘗試獲取鎖。

          最終還是來到 RedissonFairLock#tryLockInnerAsync 方法中。

          方便起見,重新貼一下 Lua 腳本,以及腳本的參數(shù)含義。

          1. KEYS[1]:加鎖的名字,anyLock
          2. KEYS[2]:加鎖等待隊(duì)列,redisson_lock_queue:{anyLock}
          3. KEYS[3]:等待隊(duì)列中線程鎖時(shí)間的 set 集合,redisson_lock_timeout:{anyLock},是按照鎖的時(shí)間戳存放到集合中的;
          4. ARGV[1]:鎖超時(shí)時(shí)間 30000
          5. ARGV[2]:UUID:ThreadId 組合 a3da2c83-b084-425c-a70f-5d9a08b37f31:1
          6. ARGV[3]:threadWaitTime 默認(rèn) 300000
          7. ARGV[4]:currentTime 當(dāng)前時(shí)間戳

          源碼分析

          第一部分,while 循環(huán):

          1. 從等待隊(duì)列 redisson_lock_queue:{anyLock} 中獲取第一個(gè)等待線程;
          2. 從等待線程超時(shí)集合 redisson_lock_timeout:{anyLock} 中獲取第一個(gè)等待線程的分?jǐn)?shù);
          3. 沒有超時(shí),直接結(jié)束,超時(shí)了,則直接移除。

          第二部分,當(dāng)前鎖存在,直接跳過。

          第三部分,當(dāng)前鎖不是持鎖線程,直接跳過。

          第四部分,

          直接返回當(dāng)前鎖還有多久到期。

          當(dāng)前 Redisson 版本為 3.15.6,不同版本的略有不同。

          隊(duì)列重排

          這里不存在重新排序,因?yàn)楣俜秸J(rèn)為這是一個(gè) bug,重新進(jìn)行了修復(fù)。

          具體可以閱讀:Justin Corpron 2019/5/10, 04:13 Fix timeout drift in RedissonFairLock

          最大的變化就是增加了第四部分。

          圖僅僅代表兩個(gè)版本的差別,并不是代表這個(gè)版本才修改。

          2

          總結(jié)

          當(dāng)線程獲取鎖失敗,進(jìn)入到等待隊(duì)列時(shí),ttl != null,在 Java 代碼中會(huì)不斷嘗試獲取鎖。

          當(dāng)鎖不存在且當(dāng)前線程是在等待隊(duì)列頭時(shí),直接獲得鎖。這個(gè)排隊(duì)的過程就是公平鎖的提現(xiàn)。


          - <End /> -




          歷史文章 | 相關(guān)推薦



          瀏覽 49
          點(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>
                  淫荡骚逼| 无码精品人妻喷潮一区二区三区白浆 | 五月天婷婷精品视频 | 久操影视 | 操进你的小穴里在线观看 |