ZooKeeper 分布式锁 Curator 源码之三:可重入锁并发加锁
前言
在了解了加锁和锁重入之后,最需要了解的还是在分布式场景下或者多线程并发加锁是如何处理的?
1并发加锁
先来看结果,在多线程对 /locks/lock_01 加锁时,是在后面又创建了新的临时节点。
这块在加锁方法 CreateBuilderImpl#pathInForeground 中已经介绍过
这里判断 /locks/lock_01 路径已经存在,会直接创建新的临时顺序节点。
真正判断锁是否获取成功,其实是在 LockInternals#attemptLock 方法中的 internalLockLoop 方法中。
加锁结果及监听
internalLockLoop 方法的主要作用是判断加锁结果,以及获取锁失败时,对其他节点的监听。
- 获取父节点 /locks/lock_01 下的所有子节点,按照从小到大排序,判断自己是不是获取到锁,没有获取到就监听自己前一个节点;
- 支持设置超时时间,超时直接返回失败;
- 不支持设置超时时间或者还没有超时,则直接 wait 等待。
是否获取锁的代码在 StandardLockInternalsDriver#getsTheLock
这块就是判断是否为最小节点,因为在 getSortedChildren 中已经对所有节点排序,所以方法中的 List
maxLeases 是在 InterProcessMutex 初始化的时候,指定的值为 1。
最终这里的结果是,判断自己是不是最小,不是最小,就将 pathToWatch 设置为前一个节点。
只监听自己的前一个节点,可以避免羊群效应!
为什么要进行等待呢?
因为是为了防止无效自旋,因为这里有监听机制,会监听上一个节点是否释放。
这块是 ZooKeeper 的 Watcher 监听机制,在节点释放的时候,会进行回调,然后使用 Java 的 notifyAll 方法通知所有的 wait 线程。然后这里的 while trye 会继续执行,重新检查是否获得锁等。
2总结
本文主要介绍了基于 ZooKeeper 的分布式锁框架 Curator 在并发场景下的锁竞争问题。
重点需要了解的是:
- 为了避免羊群效应,临时顺序节点,加锁失败后监听的是前一个节点;
- 为了避免无效自旋,这里使用了 Java 的 wait/notifyAll 机制;
- 可以看出,默认加锁就是公平锁。
本文转载自微信公众号「程序员小航」,可以通过以下二维码关注。转载本文请联系程序员小航公众号。
相关文章
- 谷歌准备发布 Fuchsia 首个开发者预览版
- 老年消费者吐槽扫码点餐:字太小 操作难
- 手机行业:关于手机的冷知识,这些你知道吗?
- 数值优化:经典随机优化算法及其收敛性与复杂度分析
- 数值优化:经典二阶确定性算法与对偶方法
- Android 12开发者预览版来了:画中画更好用 真香
- 数值优化:经典一阶确定性算法及其收敛性分析
- 老年人成为互联网时代的最大受害者!大数据乱象谁来处理?
- 数值优化:算法分类及收敛性分析基础
- 「2021」苹果怎么注册新的ID?最新、最全图文教程
- 期待已久!高德地图AR步行导航来了:走路再不怕迷路
- 6 个你可能还不知道的 iOS 小细节
- Linux:可执行程序的Shell传参格式规范
- Linux:查看磁盘配额报告数据
- 有人欢喜有人愁,315也有大赢家,3家手机厂商隐私保护做得好
- 图数据挖掘:Erdos-Renyi随机图的生成方式及其特性
- 组合数学:Burnside引理和Polya定理解决染色置换问题
- Linux:文件解压、复制和移动的若干坑
- 怎么做才能关掉手机定位?看完这几步操作,你就知道了
- 统计学习:EM算法及其在高斯混合模型(GMM)中的应用