ZooKeeper 分布式锁 Curator 源码 03:可重入锁并发加锁

前言

在了解了加锁和锁重入以后,最须要了解的仍是在分布式场景下或者多线程并发加锁是如何处理的?多线程

并发加锁

先来看结果,在多线程对 /locks/lock_01 加锁时,是在后面又建立了新的临时节点。并发

这块在加锁方法 CreateBuilderImpl#pathInForeground 中已经介绍过框架

这里判断 /locks/lock_01 路径已经存在,会直接建立新的临时顺序节点。分布式

真正判断锁是否获取成功,实际上是在 LockInternals#attemptLock 方法中的 internalLockLoop 方法中。oop

加锁结果及监听

internalLockLoop 方法的主要做用是判断加锁结果,以及获取锁失败时,对其余节点的监听。ui

  1. 获取父节点 /locks/lock_01 下的全部子节点,按照从小到大排序,判断本身是否是获取到锁,没有获取到就监听本身前一个节点;
  2. 支持设置超时时间,超时直接返回失败;
  3. 不支持设置超时时间或者尚未超时,则直接 wait 等待。

是否获取锁的代码在 StandardLockInternalsDriver#getsTheLock线程

这块就是判断是否为最小节点,由于在 getSortedChildren 中已经对全部节点排序,因此方法中的 List<String> children 是有序的。code

maxLeases 是在 InterProcessMutex 初始化的时候,指定的值为 1。blog

最终这里的结果是,判断本身是否是最小,不是最小,就将 pathToWatch 设置为前一个节点排序

只监听本身的前一个节点,能够避免羊群效应!

为何要进行等待呢?

由于是为了防止无效自旋,由于这里有监听机制,会监听上一个节点是否释放。

这块是 ZooKeeper 的 Watcher 监听机制,在节点释放的时候,会进行回调,而后使用 Java 的 notifyAll 方法通知全部的 wait 线程。而后这里的 while trye 会继续执行,从新检查是否得到锁等。

总结

本文主要介绍了基于 ZooKeeper 的分布式锁框架 Curator 在并发场景下的锁竞争问题。

重点须要了解的是:

  1. 为了不羊群效应,临时顺序节点,加锁失败后监听的是前一个节点
  2. 为了不无效自旋,这里使用了 Java 的 wait/notifyAll 机制;
  3. 能够看出,默认加锁就是公平锁

相关推荐

相关文章
相关标签/搜索