前言 一般工作中常用的分布式锁,就是基于 Redis 和 ZooKeeper,前面已经介绍完了 Redisson 锁相关的源码,下面一起看看基于 ZooKeeper 的锁.也就是 Curator 这个框架. Curator 的锁也分为很多种,本文分析共享可重入锁. 考虑到如果文章篇幅较长,不太适合阅读,所以对文章做了适当的拆分. 环境配置 本机三个节点 版本:3.7.0 系统:macOS 安装方式:brew install zookeeper Curator Maven 依赖版本:5.1.0 <…
前言 平时的工作中,由于生产环境中的项目是需要部署在多台服务器中的,所以经常会面临解决分布式场景下数据一致性的问题,那么就需要引入分布式锁来解决这一问题. 针对分布式锁的实现,目前比较常用的就如下几种方案: 基于数据库实现分布式锁 基于 Redis 实现分布式锁 [本文] 基于 Zookeeper 实现分布式锁 接下来这个系列文章会跟大家一块探讨这三种方案,本篇为 Redis 实现分布式锁篇. Redis分布式环境搭建推荐:基于Docker的Redis集群搭建 Redis分布式锁一览 说到 Re…
java高并发系列 - 第12天JUC:ReentrantLock重入锁 本篇文章开始将juc中常用的一些类,估计会有十来篇. synchronized的局限性 synchronized是java内置的关键字,它提供了一种独占的加锁方式.synchronized的获取和释放锁由jvm实现,用户不需要显示的释放锁,非常方便,然而synchronized也有一定的局限性,例如: 当线程尝试获取锁的时候,如果获取不到锁会一直阻塞,这个阻塞的过程,用户无法控制 如果获取锁的线程进入休眠或者阻塞,除非当前…
本文由https://bbs.csdn.net/topics/390939500和https://zhidao.baidu.com/question/1946051090515119908.html启发而来. 看到一个问题,Java的可重入锁为什么可以防止死锁呢?网上看了看资料,虽然有答案说出了正确答案,但是分析的不够详细,对初学者不够友好.这里我再做一个更清晰的分析. 首先是示例代码: public class Widget { public synchronized void doSomet…
我们常用的synchronized关键字是一种最简单的线程同步控制方法,它决定了一个线程是否可以访问临界区资源.同时Object.wait() 和Object.notify()方法起到了线程等待和通知的作用.这些工具对于实现复杂的多线程协作起到了重要的作用.     这里,我们介绍一种synchronized,Object.wait() 和Object.notify()方法的替代品--重入锁.首先看下重入锁的例子:       public ReentrantLock lock = new Re…
网上关于Java中锁的话题可以说资料相当丰富,但相关内容总感觉是一大串术语的罗列,让人云里雾里,读完就忘.本文希望能为Java新人做一篇通俗易懂的整合,旨在消除对各种各样锁的术语的恐惧感,对每种锁的底层实现浅尝辄止,但是在需要时能够知道去查什么. 首先要打消一种想法,就是一个锁只能属于一种分类.其实并不是这样,比如一个锁可以同时是悲观锁.可重入锁.公平锁.可中断锁等等,就像一个人可以是男人.医生.健身爱好者.游戏玩家,这并不矛盾.OK,国际惯例,上干货. 〇.synchronized与Lock…
网上关于Java中锁的话题可以说资料相当丰富,但相关内容总感觉是一大串术语的罗列,让人云里雾里,读完就忘.本文希望能为Java新人做一篇通俗易懂的整合,旨在消除对各种各样锁的术语的恐惧感,对每种锁的底层实现浅尝辄止,但是在需要时能够知道去查什么. 首先要打消一种想法,就是一个锁只能属于一种分类.其实并不是这样,比如一个锁可以同时是悲观锁.可重入锁.公平锁.可中断锁等等,就像一个人可以是男人.医生.健身爱好者.游戏玩家,这并不矛盾.OK,国际惯例,上干货. 〇.synchronized与Lock…
本文主要包含的内容:可重入锁(ReedtrantLock).公平锁.非公平锁.可重入性.同步队列.CAS等概念的理解 显式锁 上一篇文章提到的synchronized关键字为隐式锁,会自动获取和自动释放的锁,而相对的显式锁则需要在编程时指明何时获取锁,何时释放锁. 通常,锁提供对共享资源的独占访问:一次只能有一个线程可以获取锁,并且对共享资源的所有访问都需要先获取锁:而有一些锁可能允许并发访问共享资源. 本文主要讲解可重入锁(ReentrantLock),该锁为独占共享资源锁,即独占锁. 1.可…
ZooKeeper 分布式锁 Curator 源码 02:可重入锁重复加锁和锁释放 前言 加锁逻辑已经介绍完毕,那当一个线程重复加锁是如何处理的呢? 锁重入 在上一小节中,可以看到加锁的过程,再回头看 internalLock 这个方法. 加锁成功之后,将当前线程放到 threadData 中,threadData 是 ConcurrentMap<Thread, LockData> 类型的,不用担心并发问题. 假如锁重入了,直接就会在上一部分 lockData != null 被拦下,然后执行…
前言 在了解了加锁和锁重入之后,最需要了解的还是在分布式场景下或者多线程并发加锁是如何处理的? 并发加锁 先来看结果,在多线程对 /locks/lock_01 加锁时,是在后面又创建了新的临时节点. 这块在加锁方法 CreateBuilderImpl#pathInForeground 中已经介绍过 这里判断 /locks/lock_01 路径已经存在,会直接创建新的临时顺序节点. 真正判断锁是否获取成功,其实是在 LockInternals#attemptLock 方法中的 internalLo…