在学习Java语言的过程中,多线程是一个算是进阶的选择。我最近又学到了一个新技能ReentrantLock类,这个应该目前最简单的线程安全使用方式了,当然暴力synchronized除外。...ReentrantLock真的是一个非常好用的多线程安全工具类。...ReentrantLock核心(个人看法)有两个方法lock()和unlock(),顾名思义,一个是加锁一个是释放锁,所有线程安全的操作可以写在这两个方法之间。...下面演示一下ReentrantLock的基本使用,中间用到了- Java自定义异步功能实践、利用守护线程隐式关闭线程池中用到的异步关键字,有兴趣的可以翻一翻,就是关键字fun后面的代码块会有单独线程执行...,这个牵扯到ReentrantLock重入锁机制,就是一个线程可以持有很多次,但是只要次数不为零,其他线程都无法加锁成功,平时使用不多,没有谁单线程持有N多次锁: public int getHoldCount
ReentrantLock介绍 重入锁。同一个线程可以锁住多次,但是在使用完毕后,必须释放多次锁才能将锁完全释放,否则,还是该线程还是会处于阻塞状态。...并且重入锁有两种,一种是公平锁,一种是非公平锁,公平锁会把锁按照顺序轮流交付线程执行,而非公平锁不会,非公平锁会乱序选择一个线程执行。...,如果没有指定时间的话,就立即去尝试获取锁 ReentrantLock.lockInterruptibly:可以被中断的锁,加锁的线程被调用interrupt方法后,可以被中断释放锁,而不会抛出异常...ReentrantLock.isHeldByCurrentThread:判断当前的Lock是否被当前线程Hold住 ReentrantLock.getHoldCount:判断当前的锁被多少个线程引用住...ReentrantLock.hasQueuedThread:判断传入的Thread是否已经存在于锁等待队列中 ReentrantLock.hasQueuedThreads:判断当前等待队列中是否有线程正在等待锁
1.ReentrantLock加锁原理 1.第一个线程进来 FairSync里的lock方法 final void lock() { // 加锁成功后,修改的值 acquire(1); } 其抽象父类的方法...为什么头节点的线程对象要设置为空的?? 第一个线程来的时候,拿到锁,当前线程对象已经有了,aqs里的队列里不需要再保存一次,而且,队列里的对拿到锁的线程对象不做任何操作,无意义。...2.ReentrantLock解锁过程 public void unlock() { sync.release(1); } public final boolean release(int arg...),c = 0 int c = getState() - releases; // 这里判断当前线程是否是加锁的线程 if (Thread.currentThread() !...,如果只有一个线程时,没有等待队列,head = null,h = null, // 如果时多于1个线程时,h !
Lock函数 ReentrantLock中有两种Sync,一种是NonfairSync另一种是FairSync。它两同时继承Sync类。可以在创建ReentrantLock的时候指定用那种锁。...如果当前state不为0,也就是锁已经存在了的话,那么则判断尝试获取锁的线程是否为当前线程,如果为当前线程的话,那么则再将锁+1,然后设置锁状态返回true 否则返回false 在hasQueuedPredecessors...函数中,会判断,如果头尾节点不相同,并且头节点的后继为空或者头节点的后继中线程不是当前线程,就说明等待队列不为空。...如果等待队列为空的话,那么就通过CAS操作设置state,如果设置成功的话,那么就将当前线程设置成持有锁的线程,并且返回true,说明已经成功获取锁了。...否则,如果state不为0的话,那么则判断当前线程是不是就是已经持有锁的线程,如果是的话,那么就把当前状态+请求的值(1),然后设置当前的State值,饭后返回true,说明获取锁成功。
ReentrantLock与隐式锁synchronized功能相同,但ReentrantLock更具有扩展性。...ReentrantLock是线程独占的,不能与其他线程共享。所谓的重入,就是当本线程想再次获得锁,不需要重新申请,它本身就已经锁了,即重入该锁。 为什么会允许锁重入呢?...现在基于以上的认识,来看看ReentrantLock的基本实现吧。 ReentrantLock概览 ReentrantLock是实现Lock接口的。...ReentrantLock里面有一个最核心的成员变量,sync。sync的类型就是内部类Sync。它是AQS的子类,也就是说它就是实现ReentrantLock同步的工具。...至于其他成员函数,大都是围绕获取线程和队列的状态,没什么特别的,在这里不再赘述,有兴趣的可以看看源码。 总结 回顾下要点 ReentrantLock是一个可重入的锁(被当前占用的线程重入)。
一、大纲 图片 juc中的并发容器都是基于volatile变量和CAS指令实现,ReentrantLock也不例外,其类图如下所示: 图片 AQS提供了共享变量status和同步队列CLH(head、...//线程没拿到锁,进入CLH队列 2 源码分析 第一步,ReentrantLock调用lock方法,首先调用initialTryLock尝试第一次加锁。...如果没有已等待的线程且cas status成功,则加锁成功; 否则,判断本线程是否是持有锁的线程,如果有就重入,更新status。...//ReentrantLock public void lock() { sync.lock(); } //Sync final void lock() { if (!...FairSync类是公平锁,只有当同步队列中没有等待的线程或者本线程是队首线程才会尝试cas status。
ReentrantLock由上次成功锁定但是尚未解锁的线程拥有,当该锁不属于另一个线程的时候,调用lock的线程将返回,并成功获得该锁。如果当前线程已拥有该锁,则该方法将立即返回。...建议实践总是在使用try之后立即lock,最常用的是在构造前后,如: class X { private final ReentrantLock lock = new ReentrantLock...2.1 ReentrantLock() /** * Creates an instance of {@code ReentrantLock}....* This is equivalent to using {@code ReentrantLock(false)}. */ public ReentrantLock() { sync =...2.2 ReentrantLock(boolean fair) /** * Creates an instance of {@code ReentrantLock} with the * given
: A B线程打印: B C线程打印: C A线程打印: A B线程打印: B C线程打印: C 虽然,使用synchronized内置锁来控制线程协作很容易,但synchronized由于是Java...本篇,我们就来看下如何使用J.U.C的Lock工具,来实现线程交替打印字符串的功能,源码如下: static class PrintABC{ Lock lock=new ReentrantLock...A B线程打印: B C线程打印: C A线程打印: A B线程打印: B C线程打印: C A线程打印: A B线程打印: B C线程打印: C A线程打印: A B线程打印: B C线程打印...: C A线程打印: A B线程打印: B C线程打印: C 下面,我们简单分析下代码: 首先在PrintABC类里面,我们使用了Lock接口的子类ReentrantLock,ReentrantLock...扯回正题,我们这里使用了最常用的ReentrantLock来代替内置锁synchronized的功能,同时呢,为了实现线程的协作通信,我们又采用了Lock下面的Condition条件信号量,从例子的代码里面我们能发现
ReentrantLock ReentrantLock和synchronized不同,ReentrantLoock的加锁解锁都是需要手动完成的: ?...上面的打印可以看出ReentrantLock可以实现和synchronized一样的效果。...公平锁 ReentrantLock有一个带参数的构造函数: ? 默认情况下,synchronized和ReentrantLock都是非公平锁。...但是ReentrantLock可以通过传入fair = true来创建一个公平锁。公平锁是通过一个同步队列来实现多线程按申请锁的顺序获得锁。 ? 运行代码: ?...【分析】 1. 3个线程依次start,一个线程持有锁之后,另外两个线程就会被加入到ReentrantLock的同步队列中,等到当前持有锁的线程进行一次自加之后,锁被释放,此时由同步队列中下一个线程持有锁
ReentrantLock是 java提供代码层面的锁,和synchronized关键字相同。...为什么在用提供了 synchronized关键字后,还提供了ReentrantLock等代码层面的锁API,首先在synchronized关键字刚推出是,性能方面差很多,直到后面的版本中推出了锁升级的概念...分析 ReentrantLock 有如下几个特点: 1、互斥 2、重入 3、等待唤醒 4、存储一系列的等待线程 FIFO 先进先出 5、公平/非公平 使用案例 public class ReenTrantLockDemo...public ReentrantLock(boolean fair) { sync = fair ?...故如下 无线程持有时,state为0 当有线程持有时,state增长1,此时其他线程无法持有直到被释放 释放锁时,state减少1 当state恢复为0时,其他线程又可以进行抢占 当某个已经占用锁的线程再次获取到锁时
可以无阻塞尝试访问锁,使用 tryLock() 方法,具体使用如下: Lock reentrantLock = new ReentrantLock(); // 线程一 new Thread(() -›...= new ReentrantLock(); // 线程一 new Thread(() -› { try { reentrantLock.lock(); System.out.println...getQueueLength():返回正在排队等待获取此锁的线程数 isFair():该锁是否为公平锁 2.ReentrantLock 有哪些优势?...答:synchronized 和 ReentrantLock 都是保证线程安全的,它们的区别如下: ReentrantLock 使用起来比较灵活,但是必须有释放锁的配合动作; ReentrantLock...总结 本文介绍了线程同步的两种方式 synchronized 和 ReentrantLock,其中 ReentrantLock 使用更加灵活,效率也率高,不过 ReentrantLock 只能修饰代码块
线程安全解决方案 synchronized,ReentrantLock,Atomic 使用场景描述 在实际开发过程中如果服务量,请求频繁,就会经常碰见并发,这时候不做处理就会出现很多非法数据。...这时候就需要解决线程安全的问题,这时候就可以使用java当中的锁机制。...synchronized关键字一放,就解决线程安全的问题。但是还有一个问题,当前资源竞争激烈时,对于部分线程迟迟获取不到锁,这时候会出现一个锁升级的过程,且锁升级的过程是不可逆的。...static final ReentrantLock reentrantLock = new ReentrantLock(true); /** * ReentrantLock方式获取id *...ReentrantLock还可以查看锁的状态, 锁是否被锁上了. 可以查看当前有多少线程再等待锁。
https://zhuanlan.zhihu.com/p/249147493 ReentrantLock底层使用了CAS+AQS队列实现 一、CAS 1、CAS(Compare and Swap) CAS...结构如下图所示: 三、ReentrantLock的流程 首先ReentrantLock默认是非公平锁,也可以指定为公平锁 ReentrantLock的2个构造函数 public ReentrantLock...new FairSync() : new NonfairSync(); //根据参数创建 } ①ReentrantLock先通过CAS尝试获取锁, ②如果此时锁已经被占用,该线程加入AQS队列并wait...(state字段看做是每一个ReentrantLock的状态,若为0则不自由(被线程持有);否则自由) 若为0,表示锁未被占用。然后通过 !...扩充:reentrantlock.lockInterruptbly() 这个锁方法,比原来的lock方法多了一个用处,就是当t1拿到锁微释放时,t2在队列等待挂起,在主线程中可以使用t2.interrupt
前提 1)大致了解AQS原理(☆☆☆) 2)熟悉双向链表的基本操作 3)本文以公平锁上锁释放锁为例跟ReentrantLock代码(☆☆☆) 4)本文以单线程抢占锁释放锁为例(☆☆☆) 5)建议了解公平锁和非公平锁的区别...当上锁的线程释放锁后会唤醒双向链表中的第一个节点中的线程继续使用锁。...ReentrantLock lock = new ReentrantLock(true); System.out.println("--lock-");...) 释放锁 lock.unlock()跟到下面代码 //ReentrantLock public void unlock() { sync.release(1); } 继续跟进release...源码分析(一)_java_lyvee的专栏-CSDN博客_reentrantlock源码 https://ke.qq.com/course/455581?
ReentrantLock彻底解决并发线程的无限等待 马 克-to-win:上面的例子,只能做到根据请求Synchronized方法的队列里的线程的数量,决定我是否进入队列等待。...所以为求简单,我们的例子中就用ReentrantLock,ReentrantLock就是为了解决 Synchronized技术的很多弊病而生的。...马克-to-win:因为ReentrantLock类中的lockInterruptibly();方法能够让正在想 获得锁的线程被其他线程中断(见下例),从而打消原来要获得锁的计划。...当然如果没有其他的线程占有锁的话,lockInterruptibly();方法也可以让当 前线程从容获得锁。 ...import java.util.concurrent.locks.ReentrantLock; class A { private ReentrantLock lock = new ReentrantLock
通过学习本文,您将更好地理解ReentrantLock的工作原理,以及如何在多线程环境中应用它。...2.3 可重入性ReentrantLock支持可重入性,同一线程可以多次获取锁,每次获取都必须有对应的释放操作。这使得线程可以嵌套地使用锁,而不会出现死锁。3....ReentrantLock的高级特性3.1 条件变量ReentrantLock还支持条件变量,它们可以用于线程之间的协调。...通过深入理解ReentrantLock的原理和使用方法,您可以更好地编写线程安全的程序,提高多线程程序的质量和性能。在编写多线程程序时,请根据具体情况选择适当的锁机制,并考虑性能因素。...同时,多线程编程需要谨慎,合理地设计同步策略,以避免死锁和性能问题。希望本文能够帮助您更好地理解和使用ReentrantLock,使您的多线程编程之路更加顺畅。
但 synchronized 关键字是在 JVM 层面实现的,而 ReenTrantLock 是在 JDK 层面实现的。...防止线程因为无法获得锁而一直等待,常用来从外部破坏线程死锁。...线程获得 Lock 锁之后便可调用 Condition 接口的 await 方法释放锁并等待,直到有其他线程调用 Condition 的 signal 方法唤醒线程。...通过设置多个 condition 对象,多个线程等待不同的 condition 对象,可以实现选择性地叫醒线程。...public class ThreadDemo { static ReentrantLock lock = new ReentrantLock(); static Condition condition
ReentrantLock 一、 使用 1.1 简单使用 public class LockTest { // 新建锁 Lock lock = new ReentrantLock()...直到天荒地老 lock 的 tryLock 就像是一个渣男,轻轻尝试一下,不合适抓紧下一个 public class LockTest02 { // 新建锁 Lock lock = new ReentrantLock...lockInterruptibly 可以被中断 在异常捕获里捕获异常 然后做一些后置处理 public class LockTest03 { // 新建锁 Lock lock = new ReentrantLock...这样对于后边排队的是不公平的 所以称为不公平锁 在ReentrantLock的实现中,不要脸的小强会尝试好几次,最后都失败的话他才会去队尾排队 Lock可以实现公平锁:公平锁就是lock的时候会先去排队队列里边看看...如果没有自己去申请锁,如果有自己去排队,去检查有没有人排队的时候可能会出现不公平(地铁一个人一大步窜你前边了),进队列的时候也可能会出现不公平(地铁一个人一大步窜你前边了) Lock lock = new ReentrantLock
ReentrantLock 与 AQS 独占锁 上一篇文章中,我们介绍了 ReentrantLock 的用法,他就是通过 AQS 来实现的,也是 AQS 独占模式的典型示例。...接下来我们就来看看 ReentrantLock 是如何实现的。 根据类图,我们可以看到 ReentrantLock 拥有三个内部类,分别是。...ReentrantLock 的加锁与解锁 上文中我们介绍过 ReentrantLock 的加锁与解锁方法,我们来看看他们究竟是怎么实现的。 2.1....Sync 与他的两个子类 根据类图,我们可以看到,ReentrantLock 拥有一个内部类 Sync,他是 AQS 的子类,同时,ReentrantLock 还拥有另外两个内部类 — FairSync...可以看到,非公平锁的加锁与公平锁的加锁有一点不同,那就是如果当前锁状态是空闲状态,那么就可以直接获取锁,而公平锁显然是不能这么做的,因为公平锁必须要先判断 AQS 同步队列中是否有先入队的正在等待获取锁的线程
前面了解了ReentrantLock的原理,今天来应用一下,使用ReentrantLock实现两个线程的交替打印。 ?...首先定义一个AtomicInteger类型的status变量,用作计数自增,定义一个ReentrantLock锁,定义两个锁条件:奇数条件、偶数条件。 ?...,打印出偶数,然后调用oushu.signal()方法唤醒在等待队列中的奇数线程;如果是奇数,则打印奇数后,唤醒偶数线程,获取锁后进行打印。...//使当前线程加入 await() 等待队列中,并释放当锁,当其他线程调用signal()会重新请求锁。与Object.wait()类似。...void await() throws InterruptedException; //唤醒一个在 await()等待队列中的线程。
领取专属 10元无门槛券
手把手带您无忧上云