简介 curator的recipes实现了可重入互斥锁,允许你在分布式场景下多个进程之间实现锁的互斥以协调多进程执行. 相关类:InterProcessMutex 官方文档:http://curator.apache.org/curator-recipes/shared-reentrant-lock.html javaDoc:http://curator.apache.org/apidocs/org/apache/curator/framework/recipes/locks/InterProc…
简介 recipes的InterProcessSemaphoreMutex是一种不可重入的互斥锁,也就意味着即使是同一个线程也无法在持有锁的情况下再次获得锁,所以需要注意,不可重入的锁很容易在一些情况导致死锁,比如你写了一个递归. 官方文档:http://curator.apache.org/curator-recipes/shared-lock.html javaDoc:http://curator.apache.org/curator-recipes/shared-lock.html 代码示…
目录 基本用法介绍 继承体系 构造方法 state状态表示 获取锁 void lock()方法 NonfairSync FairSync 公平与非公平策略的差异 void lockInterruptibly() boolean tryLock()方法 boolean tryLock(long timeout, TimeUnit unit) 释放锁 void unlock()方法 Condition实现生产者消费者 总结 参考阅读 系列传送门: Java并发包源码学习系列:AbstractQueu…
一个线程执行synchronized同步代码时,再次重入该锁过程中,如果抛出异常,会释放锁吗? 如果锁的计数器为1,抛出异常,会直接释放锁: 那如果锁的计数器为2,抛出异常,会直接释放锁吗? 来简单测试一下 @Slf4j public class SynchronizedExceptionRunnable implements Runnable { private volatile boolean flag = true; @Override public void run() { synchr…
1.引子 "ReentrantLock"单词中的“Reentrant”就是“重入”的意思,正如其名,ReentrantLock是一个支持重入的排他锁,即同一个线程中可以多次获得同步状态,常表现为lock()方法的嵌套使用(类似于synchronized代码类嵌套),而在AQS类注释的使用说明中的Mutex是一个不可重入的锁,只要一个线程获得了同步状态,再次tryAcquire(int)返回false. 另外ReentrantLock还支持公平锁和非公平锁的的选择,公平锁是指等待时间长的…
简介 curator实现了跨JVM的可重入读写互斥锁.它使用zookeeper去进行加锁,所以指定相同路径的处理线程将会基于“公平锁”的机制去竞争锁资源. 读写锁包含了读锁.写锁两个,它们的互斥关系如下: 1)读写互斥: 2)写写互斥: 3)读读不互斥. 重入性:读写锁是可以重入的,意味着你获取了一次读锁/写锁,那么你可以再次获取.但是要记得最后释放锁,获取了几次就得释放几次. 降级/升级:写锁可以降级成读锁,但是读锁不能升级成写锁否则会导致循环等待最终死锁. 官方文档:http://curat…
前言 主流的分布式锁一般有三种实现方式: 数据库乐观锁 基于Redis的分布式锁 基于ZooKeeper的分布式锁 之前我在博客上写过关于mysql和redis实现分布式锁的具体方案:https://www.cnblogs.com/wang-meng/p/10226618.html里面主要是从实现原理出发. 这次[分布式锁]系列文章主要是深入redis客户端reddision源码和zk 这两种分布式锁的实现原理. 可靠性 首先,为了确保分布式锁可用,我们至少要确保锁的实现同时满足以下四个条件:…
通常如果在单机环境,使用synchronized或juc ReentrantLock 实现锁机制,但如果是分布式系统,则需要借助第三方工具实现,比如redis.zookeeper等.redis为单进程单线程模式,操作都是原子过程,采用队列模式将并发访问变成串行访问,且多客户端对redis的连接并不存在竞争关系.--------------------- 一.redis 基本命令setnx 命令(『SET if Not eXists』(如果不存在,则 SET)的简写):设置成功,返回 1 .设置失…
一.锁重入 package com.roocon.thread.t6; public class Demo { /* 当第一个线程A拿到当前实例锁后,进入a方法,那么,线程A还能拿到被当前实例所加锁的另一个 同步方法b吗?是不是只有当线程A释放了a方法的同步锁后,才可以去获取b方法的同步锁呢? */ public synchronized void a(){ System.out.println("a"); b(); } public synchronized void b(){ Sy…
public class ReentrantReadWriteLockTest { public static void main(String[] args) throws InterruptedException { // testReenter(); // testUpgrade(); testDowngrade(); } /** * 在同一个线程中,在没有释放写锁的情况下,就去申请读锁,这属于锁降级,ReentrantReadWriteLock是支持的,不过锁的释放有问题,获取到锁就要释…
1. MyAQS介绍    在这个系列博客中,我们会参考着jdk的AbstractQueuedLongSynchronizer,从零开始自己动手实现一个AQS(MyAQS).通过模仿,自己造轮子来学习主要有两个好处,一是可以从简单到复杂,从核心逻辑再到旁路逻辑的实现,学习曲线较为平滑:二是可以站在设计者的角度去思考实现具体功能时可以采用的各种方案的优劣,更深刻的理解其设计的精妙.关键之处. AQS支持互斥和共享这两种工作模式,其中互斥模式比共享模式要简单许多.本着由浅入深的原则,本篇博客实现的M…
Curator是ZooKeeper的一个客户端框架,其中封装了分布式互斥锁的实现,最为常用的是InterProcessMutex,本文将对其进行代码剖析 简介 InterProcessMutex基于Zookeeper实现了分布式的公平可重入互斥锁,类似于单个JVM进程内的ReentrantLock(fair=true) 构造函数 1234567891011121314151617 // 最常用public InterProcessMutex(CuratorFramework client, St…
前言 本篇适用于了解ReentrantLock或ReentrantReadWriteLock的使用,但想要进一步了解原理的读者.见于之前的分析都是借鉴大量的JDK源码,这次以流程图的形式代替源码,希望读者能有更好的阅读体验.有兴趣了解源码的读者也可以借鉴本篇的分析成果做源码分析. 在<从源码分析ReentrantLock原理>这一篇文章中分析了以非阻塞同步算法为基础实现的可重入独占锁ReentrantLock.所谓** “独占” 即同一时间只能有一个线程持有锁.而 “重入” **是指该线程如果…
此篇博客所有源码均来自JDK 1.8 ReentrantLock,可重入锁,是一种递归无阻塞的同步机制.它可以等同于synchronized的使用,但是ReentrantLock提供了比synchronized更强大.灵活的锁机制,可以减少死锁发生的概率. API介绍如下: 一个可重入的互斥锁定 Lock,它具有与使用 synchronized 方法和语句所访问的隐式监视器锁定相同的一些基本行为和语义,但功能更强大.ReentrantLock 将由最近成功获得锁定,并且还没有释放该锁定的线程所拥…
最近在读<<Java并发编程实践>>,在第二章中线程安全中降到线程锁的重进入(Reentrancy) 当一个线程请求其它的线程已经占有的锁时,请求线程将被阻塞.然而内部锁是可重进入的,因此线程在试图获得它自己占用的锁是,请求会成功.重进入意味着请求是基于“每一个线程”,而不是基于“每一次调用”(互斥锁是基于每次调用的).重进入的实现是通过为每一个锁关联一个请求技术器和一个占有他的线程.当计数为0时,认为锁是未被占用的.线程请求一个未被占有的锁时候,JVM将记录锁的占有者,并且将请求…
每个Java对象都可以用做一个实现同步的锁,这些锁被称为内置锁或监视器锁.线程在进入同步代码块之前会自动获取锁,并且在退出同步代码块时会自动释放锁.获得内置锁的唯一途径就是进入由这个锁保护的同步代码块或方法. 当某个线程请求一个由其他线程持有的锁时,发出请求的线程就会阻塞.然而,由于内置锁是可重入的,因此如果摸个线程试图获得一个已经由它自己持有的锁,那么这个请求就会成功."重入"意味着获取锁的操作的粒度是"线程",而不是调用.重入的一种实现 方法是,为每个锁关联一个…
写在前面 ReentrantLock,可重入锁,是一种递归无阻塞的同步机制.它可以等同于synchronized的使用,但是ReentrantLock提供了比synchronized更强大.灵活的锁机制,可以减少死锁发生的概率. API介绍如下: 一个可重入的互斥锁定 Lock,它具有与使用 synchronized 方法和语句所访问的隐式监视器锁定相同的一些基本行为和语义,但功能更强大.ReentrantLock 将由最近成功获得锁定,并且还没有释放该锁定的线程所拥有.当锁定没有被另一个线程所…
每个Java对象都可以用做一个实现同步的锁,这些锁被称为内置锁或监视器锁.线程在进入同步代码块之前会自动获取锁,并且在退出同步代码块时会自动释放锁.获得内置锁的唯一途径就是进入由这个锁保护的同步代码块或方法. ​ 当某个线程请求一个由其他线程持有的锁时,发出请求的线程就会阻塞.然而,由于内置锁是可重入的,因此如果摸个线程试图获得一个已经由它自己持有的锁,那么这个请求就会成功."重入"意味着获取锁的操作的粒度是"线程",而不是调用.重入的一种实现方法是,为每个锁关联一…
目录 1. ReentrantLock简介 2. ReentrantLock和synchronized的相同点 2.1 ReentrantLock是独占锁且可重入的 3. ReentrantLock相比synchronized的额外功能 3.1 ReentrantLock可以实现公平锁. 3.2 .ReentrantLock可响应中断 3.3 获取锁时限时等待 4. 结合Condition实现等待通知机制 4.1 Condition使用简介 4.2 使用Condition实现简单的阻塞队列 5.…
本文仅基于可重入的锁(ReentrantLock类)对AQS做分析,只考虑独占锁. 共享锁与独占锁的更多信息,以后再讨论. AQS中队列的实现 节点Node AQS的节点包含了对前置节点的引用pre,后置节点的引用next,以及持有节点的线程thread. static final class Node { /** pre节点,主要用来实现取消 * Link to predecessor node that current node/thread relies on * for checking…
1. ReentrantLock简介 jdk中独占锁的实现除了使用关键字synchronized外,还可以使用ReentrantLock.虽然在性能上ReentrantLock和synchronized没有什么区别,但ReentrantLock相比synchronized而言功能更加丰富,使用起来更为灵活,也更适合复杂的并发场景. 2. ReentrantLock和synchronized的相同点 2.1 ReentrantLock是独占锁且可重入的 例子 public class Reentr…
前言 相信小伙伴都是使用分布式服务,那一定绕不开分布式服务中数据并发更新问题! 单系统很容易想到 Java 的各种锁,像 synchronize.ReentrantLock 等等等,那分布式系统如何处理? 当然是使用分布式锁. 如果小伙伴不知道什么是分布式锁,那推荐看看石杉老师的突击课或者在网上搜一搜相关资料. 当使用 Redis 作为分布式锁时,当前使用较多的框架就是 Redisson. 当然 Redisson 也不仅仅只能当做锁来使用,也有很多其他的功能,小伙伴们可以看一看官方文档,自己多动…
一个小例子帮助理解(我们常用的synchronized也是可重入锁) 话说从前有一个村子,在这个村子中有一口水井,家家户户都需要到这口井里打水喝.由于井水有限,大家只能依次打水.为了实现家家有水喝,户户有水用的目标,村长绞尽脑汁,最终想出了一个比较合理的方案. 首先,在水井边上安排一个看井人,负责维持秩序. 然后,打水时,以家庭为单位,哪个家庭任何人先到井边,就可以先打水,而且如果一个家庭占到了打水权,其家人这时候过来打水不用排队.而那些没有抢占到打水权的人,一个一个挨着在井边排成一队,先到的排…
可重入锁,指的是以线程为单位,当一个线程获取对象锁之后,这个线程可以再次获取本对象上的锁,而其他的线程是不可以的. synchronized 和   ReentrantLock 都是可重入锁. 可重入锁的意义之一在于防止死锁. 实现原理实现是通过为每个锁关联一个请求计数器和一个占有它的线程.当计数为0时,认为锁是未被占有的:线程请求一个未被占有的锁时,JVM将记录锁的占有者,并且将请求计数器置为1 . 如果同一个线程再次请求这个锁,计数器将递增: 每次占用线程退出同步块,计数器值将递减.直到计数…
关于线程安全的例子,我前面的文章Java并发编程:线程安全和ThreadLocal里面提到了,简而言之就是多个线程在同时访问或修改公共资源的时候,由于不同线程抢占公共资源而导致的结果不确定性,就是在并发编程中经常要考虑的线程安全问题.前面的做法是使用同步语句synchronized来隐式加锁,现在我们尝试来用Lock显式加锁来解决线程安全的问题,先来看一下Lock接口的定义: public interface Lock 1 Lock接口有几个重要的方法: //获取锁,如果锁不可用,出于线程调度目…
以下内容转自http://ifeve.com/reentrance-lockout/: 重入锁死与死锁和嵌套管程锁死非常相似.锁和读写锁两篇文章中都有涉及到重入锁死的问题. 当一个线程重新获取锁,读写锁或其他不可重入的同步器时,就可能发生重入锁死.可重入的意思是线程可以重复获得它已经持有的锁.Java的synchronized块是可重入的.因此下面的代码是没问题的: (译者注:这里提到的锁都是指的不可重入的锁实现,并不是Java类库中的Lock与ReadWriteLock类) public cl…
java高并发系列 - 第12天JUC:ReentrantLock重入锁 本篇文章开始将juc中常用的一些类,估计会有十来篇. synchronized的局限性 synchronized是java内置的关键字,它提供了一种独占的加锁方式.synchronized的获取和释放锁由jvm实现,用户不需要显示的释放锁,非常方便,然而synchronized也有一定的局限性,例如: 当线程尝试获取锁的时候,如果获取不到锁会一直阻塞,这个阻塞的过程,用户无法控制 如果获取锁的线程进入休眠或者阻塞,除非当前…
举例来说明锁的可重入性 public class UnReentrant{ Lock lock = new Lock(); public void outer(){ lock.lock(); inner(); lock.unlock(); } public void inner(){ lock.lock(); //do something lock.unlock(); } } outer 中调用了 inner,outer 先锁住了 lock,这样 inner 就不能再获取 lock.其 实调用…
举例来说明锁的可重入性 public class UnReentrant{ Lock lock = new Lock(); public void outer(){ lock.lock(); inner(); lock.unlock(); } public void inner(){ lock.lock(); //do something lock.unlock(); } } outer 中调用了 inner,outer 先锁住了 lock,这样 inner 就不能再获取 lock.其 实调用 …
在多线程环境中,多个线程可能会同时访问同一个资源,为了避免访问发生冲突,可以根据访问的复杂程度采取不同的措施 原子操作适用于简单的单个操作,无锁算法适用于相对简单的一连串操作,而线程锁适用于复杂的一连串操作 原子操作 修改状态要么成功且状态改变,要么失败且状态不变,并且外部只能观察到修改前或者修改后的状态,修改中途的状态不能被观察到 .NET 中,System.Threading.Interlocked 类提供了用于执行原子操作的函数,这些函数接收引用参数(ref),也就是变量的内存地址,然后针…