画分布式锁之"通文馆圣主"Curator的"十三太保"(下)

       上一篇,我们基于示例和源码去剖析了可重入互斥锁,不可重入互斥锁,信号量锁,参见【画分布式锁之"通文馆圣主"Curator的"十三太保"(上) 】,Curator圣主的强大,Zookeeper的健壮性,都让zk分布式锁不可匹敌,本文将继续分析剩余的分布式锁,让我们一起江湖里过招吧。

勇,联合锁 && 加锁 && 释放锁

       联合锁,multiLock,这个我们之前也是分析过的,申请多个小锁,合并成一个大锁,并且要保证这多个小锁都要在规定时间内要加锁成功,才算加锁成功,进行业务逻辑处理,最后也是要依次释放所有的锁。

这个锁借助的还是一开始讲的互斥锁,加锁流程并不复杂,我们来看看源码,其实就是对三把锁进行遍历,每一把都单独加锁,每次加锁成功就会放入一个list中,一旦出现一个锁加

锁失败,那么就会对已经加锁成功的几把锁,都进行释放操作。释放操作呢,就更简单了,就是对所有已经加锁成功的锁进行遍历,将所有的锁的一一释放,把对应的节点删除就OK了。到这一把锁,还是很easy的。

【忍,读写锁 && 加锁 && 释放锁

       读写锁的分析呢,之前也分析过,无非是要去分析读写,读读,写写,写读之前是否互斥,能否重入。我们一点点分析,相信经过多次分析,对这些也是轻车熟路,go~go~。

读写锁  && 读读

       首先当我们创建一个读写锁对象InterProcessReadWriteLock的时候,就会实例化一个读锁对象和一个写锁对象,InternalInterProcessMutex我们可以看出,这个对象是继承于InterProcessMutex互斥锁对象,并且重写了一些方法。那我们先来看自读锁对象,这个对象也是继承于互斥锁,重写了一些方法,一开始的节奏和互斥锁一样,我们一步步往下看,看看哪里发生了变化,关键的点在哪里。

我们跟着加锁方法【 acquire() 】debug,前面的流程和互斥锁完全一样,先从本地缓存map中看看有没有当前线程对应的锁信息对象,然后就是就是调用【attemptLock()】方法去尝试获取锁,一堆变量赋值之后,进入到无限循环,只是这里我们将基于path="/locks/lock_01/__READ__"创建节点,得到的ourPath=/locks/lock_01/_c_92805df7-1f14-41c7-ab8b-86b3f66577dd-__READ__0000000025,显而易见,这是读相关的一个节点。接着调用【internalLockLoop()】方法,还是进入一个while的无限循环,先是【 getSortedChildren】获取排完序的子节点列表,此时节点就是当前025节点,然后就调用了【 getsTheLock 】方法,这里我们就会发现它走的是子类实现的方法,不是原来互斥锁的方法了。

       首先,if判断了当前线程是不是持有写锁,这个我们后面分析,我们接着往下看,有几个关键变量我们需要重点关注一下,【 index=0,firstWriteIndex=2147483647,ourIndex=2147483647】,遍历之前的children列表,先是判断是否包含写标识“_WRIT_”,这里肯定不是,判断节点路径是否包含sequenceNodeName=_c_e54fe0fa-185f-4802-9c38-ae3b7cc0d131-__READ__0000000030,如果包含,就执行ourIndex=index,然后break;其实就是定位一下我们传过来的节点在children中的角标位置。ourIndex=index=0;

       紧接着,校验一波ourIndex有没有问题,如果ourIndex小于0,就抛出异常;好,关键的判断在这里【boolean getsTheLock=(ourIndex < firstWriteIndex)】,这里0<2147483647,成立,就封装结果对象返回了。一路返回,获取锁成功。并且将锁和当前线程绑定起来,存到本地缓存中。

        那么,假设当前已经有一个客户端线程持有锁了,另一个线程来获取读锁呢?我们可以根据上面的流程来梳理一下,之前最核心的判断就是ourIndex是否小于firstWriteIndex,此时的firstWriteIndex等于Integer.MaxValue,相当于这么多客户端同时加锁是没有问题的,结论:【读读不互斥,多个客户端加读锁不互斥,最多可以有2147483647个客户端同时加读锁】。

读写锁  && 读写

       那么当前有客户端获取了读锁,另一个客户端来获取写锁呢?我们就要来看看加写锁的流程。前面的加锁流程都是一样的,基于path=/locks/lock_01/__WRIT__,创建节点,获得ourPath=/locks/lock_01/_c_ef3510d2-56a1-4f43-a9b8-212ddf4e3dcc-__WRIT__0000000033,一路往下走,到达【getsTheLock】方法,我们可以看到这样一个关键判断【 ourIndex 】,此时呢,我们的写节点在列表的第二个,他的前面有一个读锁,那么ourIndex=1读写互斥,当已经有客户端加读锁的情况下,写锁将加锁失败,直到所有的读锁都释放,才可能加写锁成功。】

     【 读写锁  && 写读

       再来看看当一个客户端加了写锁的情况下,加读锁会不会互斥?还记得上文我们分析读锁的加锁过程中,下面这个判断语句吗?当当前的线程

持有写锁的时候,是直接返回加锁成功的,那么在这种情况下,加读锁是没有问题的。如果这个判断不成立,不是当前线程持有写锁,我们接着往下看,还是关注这几个关键的变量,此时呢第一个节点是写锁【firstWriteIndex=index=0,ourIndex=i++=1】,在接下来的判断中可

以看到【ourIndex=1<firstWriteIndex=0】不成立,这句话也说明了有写锁的时候不是同一个客户端线程就不能加读锁,那么接下来就会继续走监听前一个节点,等待前一个节点释放,【注意的是这里的节点是写锁节点】,等待加锁的流程。当后面有很多客户端要加读锁也是一样的,要排队等待写锁节点释放,才会加锁成功,结论:【当 当前客户端线程持有写锁时,当前客户端线程加读锁不互斥,其他客户端线程加读锁互斥。

读写锁  && 写写

       如果一个客户端加了写锁,另一个客户端来加写锁,又当如何呢?回想一下上文说的写锁加锁流程,此时我们尝试加锁的节点在children列表的第二个,不是第一位,【 ourIndex <maxLeases】,1<1不成立,所以加锁失败,也必须要等前一个节点释放,前一个写锁释放,第二个写锁才能加锁成功。结论:【读写锁,写写互斥】。

       到这里,我们就把Curator圣主门下的分布式锁系列大概说全了,江湖里需要用这些手段去历练一番,才能得心应手,Curator的能力不止这些,还有很多核心能力值得我们去探索,今天就写到这里啦,夜已深了,最近的流感好像有人心惶惶了,每个小伙伴都要呵护身体,为自己和家人留一个好身体。文中有什么问题和错误,欢迎留言指正,批评,谢谢大家,晚安。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,012评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,589评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,819评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,652评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,954评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,381评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,687评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,404评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,082评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,355评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,880评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,249评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,864评论 3 232
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,007评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,760评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,394评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,281评论 2 259

推荐阅读更多精彩内容