前言

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

并发加锁

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

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

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

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

加锁结果及监听

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

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

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

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

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

最终这里的结果是,判断自己是不是最小,不是最小,就将 pathToWatch 设置为前一个节点

只监听自己的前一个节点,可以避免羊群效应!

为什么要进行等待呢?

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

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

总结

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

重点需要了解的是:

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

相关推荐

ZooKeeper 分布式锁 Curator 源码 03:可重入锁并发加锁的更多相关文章

  1. ZooKeeper 分布式锁 Curator 源码 04:分布式信号量和互斥锁

    前言 分布式信号量,之前在 Redisson 中也介绍过,Redisson 的信号量是将计数维护在 Redis 中的,那现在来看一下 Curator 是如何基于 ZooKeeper 实现信号量的. 使 ...

  2. ZooKeeper 分布式锁 Curator 源码 02:可重入锁重复加锁和锁释放

    ZooKeeper 分布式锁 Curator 源码 02:可重入锁重复加锁和锁释放 前言 加锁逻辑已经介绍完毕,那当一个线程重复加锁是如何处理的呢? 锁重入 在上一小节中,可以看到加锁的过程,再回头看 ...

  3. ZooKeeper 分布式锁 Curator 源码 01:可重入锁

    前言 一般工作中常用的分布式锁,就是基于 Redis 和 ZooKeeper,前面已经介绍完了 Redisson 锁相关的源码,下面一起看看基于 ZooKeeper 的锁.也就是 Curator 这个 ...

  4. redis实现分布式锁需要考虑的因素以及可重入锁实现

    死锁 错误例子 解决方式  防止死锁 通过设置超时时间  不要使用setnx key   expire 20  不能保证原子性 如果setnx程序就挂了 没有执行expire就死锁了  reidis2 ...

  5. ReentrantLock可重入锁——源码详解

    开始这篇博客之前,博主默认大家都是看过AQS源码的~什么居然没看过猛戳下方 全网最详细的AbstractQueuedSynchronizer(AQS)源码剖析(一)AQS基础 全网最详细的Abstra ...

  6. ReentrantLock(重入锁)简单源码分析

    1.ReentrantLock是基于AQS实现的一种重入锁. 2.先介绍下公平锁/非公平锁 公平锁 公平锁是指多个线程按照申请锁的顺序来获取锁. 非公平锁 非公平锁是指多个线程获取锁的顺序并不是按照申 ...

  7. redis分布式锁-可重入锁

    redis分布式锁-可重入锁 上篇redis实现的分布式锁,有一个问题,它不可重入. 所谓不可重入锁,即若当前线程执行某个方法已经获取了该锁,那么在方法中尝试再次获取锁时,就会获取不到被阻塞. 同一个 ...

  8. java高并发系列 - 第12天JUC:ReentrantLock重入锁

    java高并发系列 - 第12天JUC:ReentrantLock重入锁 本篇文章开始将juc中常用的一些类,估计会有十来篇. synchronized的局限性 synchronized是java内置 ...

  9. Java多线程——深入重入锁ReentrantLock

    简述 ReentrantLock 是一个可重入的互斥(/独占)锁,又称为“独占锁”. ReentrantLock通过自定义队列同步器(AQS-AbstractQueuedSychronized,是实现 ...

随机推荐

  1. CPU消耗,跟踪定位理论与实践

    CPU消耗,跟踪定位理论与实践 一.性能指标之资源指标定位方案 1.打tprof报告方法 抓取perfpmr文件 60秒. perfpmr.sh 60 从结果文件中取出tprof.sum 或直接抓取t ...

  2. Hdoop

    优势:1.低成本  2.高扩展 3.成熟的生态圈 1.安装虚拟机 vi /etc/profile

  3. 获取微信公众号的粉丝openid以及用openid获取unionID

    第一步获取微信粉丝的openid https://api.weixin.qq.com/cgi-bin/user/get?access_token=access_token access_token这里 ...

  4. R语言读取文件

    1.R语言读取文件,文件类型为.txt 直接使用read.table()即可,若不知道当前的工作目录,可以使用函数getwd()来查看 2.R语言读取文件,文件类型为.xlsx 方法一:可以把excl ...

  5. 安聊服务端Netty的应用

    Netty简介 Netty是一个面向网络编程的Java基础框架,它基于异步的事件驱动,并且内置多种网络协议的支持,可以快速地开发可维护的高性能的面向协议的服务器和客户端. 安聊简介 安聊是一个即时聊天 ...

  6. 解决 ORA-12154 TNS无法解析指定的连接标识符

    相信作为ORACLE数据库的开发人员没有少碰到"ORA-12154: TNS: 无法解析指定的连接标识符",今天我也又碰到了类似的情况,将我的解决方法进行小结,希望能对碰到同样问题 ...

  7. vue cli3 创建项目

    1.确认是否由安装由vue 命令提示符 执行 vue -V 如果没有则执行 npm uninstall vue-cli 2.创建项目 vue create demo1 具体操作如下: (1)执行以上命 ...

  8. CRM系统为什么达不到预期效果?

    随着信息技术的发展,企业对于信息化转型的需求越发强烈,而CRM客户关系管理系统成为了企业信息化转型的首选.尽管CRM系统对于企业有着很重要的作用,但有不少企业在选型和实施时遇到了问题,导致CRM系统没 ...

  9. drf-路由和认证

    目录 一.路由Routers SimpleRouter DefaultRouter action的使用 二.认证 认证的写法 认证源码分析 认证组件的使用 一.路由Routers 在 Rest Fra ...

  10. Java程序设计(2021春)——第二章笔记与思考

    Java程序设计(2021春)--第二章笔记与思考 本章概览: 面向对象方法的特征 抽象:从同类型对象中抽象出共同属性 封装:把数据和处理数据的方法封到一个类中 继承:在已有的类的基础上开发新的类 多 ...