前言

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

并发加锁

先来看结果,在多线程对 /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. Auto ML自动特征工程

    Auto ML自动特征工程 特征工程是在做机器学习训练的过程中必不可少的环节,特征工程就是找出对模型结果有益的特征交叉关系,通常特征工程需要耗费算法工程师大量的精力去尝试.针对这样的场景,PAI推出智 ...

  2. 尚硅谷Java——宋红康笔记【day11-day18】

    day11 Eclipse中的快捷键: * 1.补全代码的声明:alt + / * 2.快速修复: ctrl + 1 * 3.批量导包:ctrl + shift + o * 4.使用单行注释:ctrl ...

  3. 端午总结Vue3中computed和watch的使用

    1使用计算属性 computed 实现按钮是否禁用 我们在有些业务场景的时候,需要将按钮禁用. 这个时候,我们需要使用(disabled)属性来实现. disabled的值是true表示禁用.fals ...

  4. 【九】Kubernetes 之 Service 概念图文讲解及功能演示

    Service 概念 Kubernetes Service 定义了这样一种抽象:逻辑上的一组 Pod,一种可以访问它们的策略 -- 通常称为微服务. Service 通常是通过 Label Selec ...

  5. PTA4-6题目集总结与归纳

    前言: 继上篇blog所写的几种日期的求法,这次是把那几种聚合起来,即日期类的聚合设计.除下这类,一种是图形继承设计的3种变化,还有一种是3次对正则表达式的应用.当然,作为一个菜鸟,还是无法写成大佬的 ...

  6. 万字长文详解HiveSQL执行计划

    Hive SQL的执行计划描述SQL实际执行的整体轮廓,通过执行计划能了解SQL程序在转换成相应计算引擎的执行逻辑,掌握了执行逻辑也就能更好地把握程序出现的瓶颈点,从而能够实现更有针对性的优化.此外还 ...

  7. 判断Linux 系统负荷是否过载

    1.如果你的电脑很慢,可以查看下它的工作量是否太大. 在Linux系统中,我们一般使用uptime,或者w 或者top命令 如下:在操作系统中输入 :uptime 08:55:44 up 23 day ...

  8. Linux添加永久静态路由

    1.首先查看一下本机的路由 route -n 2.比如我们添加两条静态路由,访问192.168.142.100时通过192.168.142.10:访问192.168.142.200时通过192.168 ...

  9. HashMap 中7种遍历方式的性能分析

    随着 JDK 1.8 Streams API 的发布,使得 HashMap 拥有了更多的遍历的方式,但应该选择那种遍历方式?反而成了一个问题. 本文先从 HashMap 的遍历方法讲起,然后再从性能. ...

  10. .Net Core Host 之详解

    简介: 开发使用有三年经验了,想趁这个机会把net core的知识点梳理一下,也更好的研究一下.NET 5给我们带来的变化. 主机的概念: 一个主机是封装了应用程序的资源,比如一个对象: 依赖注入 ( ...