ReentrantLock是一个互斥的同步器,其实现了接口Lock,里面的功能函数主要有:
1. lock()-- 阻塞模式获取资源
2. lockInterruptibly() -- 可中断模式获取资源
3. tryLock() -- 尝试获取资源
4. tryLock(time) -- 在一段时间内尝试获取资源
5. unlock() -- 释放资源
ReentrantLock实现Lock有两种模式即公平模式和不公平模式
Concurrent包下的同步器都是基于AQS框架,在ReentrantLock里面会看到这样三个类
static abstract class Sync extends AbstractQueuedSynchronizer {
abstract void lock();
final boolean nonfairTryAcquire(int acquires) { ... }
protected final boolean tryRelease(int releases) { ... }
}
final static class NonfairSync extends Sync {
protected final boolean tryAcquire(int acquires) { ... }
final void lock() { ... }
}
final static class FairSync extends Sync {
final void lock() { ...}
protected final boolean tryAcquire(int acquires) { ... }
}
再回归到ReentrantLock对Lock的实现上,
0. ReentrantLock实例化
ReentrantLock有个属性sync,实际上对Lock接口的实现都是包装了一下这个sync的实现
如果是公平模式则创建一个FairSync对象,否则创建一个NonfairSync对象,默认是不公平模式
1. lock() 调用sync.lock():
公平模式下:直接走AQS的acquire函数,此函数的逻辑走一次tryAcquire,如果成功: 线程拜托同步器的控制,否则加入NODE链表,进入acquireQueued的tryAcquire,休眠,被唤醒的轮回不公平模式下和公平模式下逻辑大体上是一样的,不同点有两个:
a)在执行tryAcquire之前的操作,不公平模式会直接compareAndSetState(0, 1)原子性的设置AQS的资源,0表示目前没有线程占据资源,则直接抢占资源,不管AQS的NODE链表的FIFO原则
b)tryAcquire的原理不一样,不公平模式的tryAcquire只看compareAndSetState(0, 1)能否成功而公平模式还会加一个条件就是此线程对于的NODE是不是NODE链表的第一个
c)由于tryAcquire的实现不一样,而公平模式和不公平模式在lock期间走的逻辑是一样的(AQS的acquireQueued的逻辑
d)对于一个线程在获取到资源后再调用lock会导致AQS的资源做累加操作,同理线程要彻底的释放资源就必须同样 次数的调用unlock来做对应的累减操作,因为对应ReentrantLock来说tryAcquire成功一个必须的条件就是compareAndSetState(0, 1)
e)由于acquireQueued过程中屏蔽了线程中断,只是在线程拜托同步器控制后,如果记录线程在此期间被中断过则标记线程的中断状态
2. lockInterruptibly() 调用sync.acquireInterruptibly(1),上一篇文章讲过AQS的核心函数,这个过程和acquireQueued是一样的,只不过在阻塞期间如果被标记中断则线程在park期间被唤醒,然后直接退出那个轮回,抛出中断异常
由于公平模式和不公平模式下对tryAcquire的实现不一样导致lockInterruptibly逻辑也是不一样
3. tryLock() 函数只是尝试性的去获取一下锁,跟tryAcquire一样,这两种模式下走的代码一样都是公平模式下的代码
4. tryLock(time) 调用sync.tryAcquireNanos(time),上一篇文章讲过AQS的核心函数,这个过程和acquireQueued一样,
a)在阻塞前会先计算阻塞的时间,进入休眠
b) 如果被中断则会判断时间是否到了
1. 如果没到则且被其他线程设置了中断标志,退出那个轮回,抛出中断异常,如果没有被设置中断标记则是前一个线程释放了资源再唤醒了它,其继续走那个轮回,轮回中,如果tryAcquire成功则摆脱了同步器的控制,否则回到
2. 如果时间到了则退出轮回,获取资源失败
5. unlock() 调用sync.release(1),上一篇文章讲过AQS的核心函数,release函数会调用Sync实现的tryRelease函数来判断释放资源是否成功,即Sync.tryRelease函数,其逻辑过程是
a. 首先判断目前占据资源的线程是不是调用者,如果不是会抛出异常IllegalMonitorStateException
b. 如果是则进行AQS资源的减1逻辑,如果再减1后AQS资源变成0则表示调用线程测得放弃了此锁,返回给release的值的TRUE,release会唤醒下一个线程
-----------------------------------------------------------------------
整体来看ReentrantLock互斥锁的实现大致是
1. 自己实现AQS的tryAcquire和tryRelease逻辑,tryAcquire表示尝试去获取锁,tryRelease表示尝试去释放锁
2. ReentrantLock对lock(),trylock(),trylock(time),unlock()的实现都是使用AQS的框架,然后AQS的框架又返回调用ReentrantLock实现的tryAcquire和tryRelease来对线程是否获取锁和释放锁成功做出依据判断
分享到:
相关推荐
ReentrantLock java除了使用关键字synchronized外,还可以使用ReentrantLock实现独占锁的功能。而且ReentrantLock相比synchronized而言功能更加丰富,使用起来更为灵活,也更适合复杂的并发场景。这篇文章主要是从...
java语言 并发编程 ReentrantLock与synchronized区别 详解
ReentrantLock的使用及注意事项
1、ReentrantLock简介 2、ReentrantLock函数列表 3、重入的实现 4、公平锁与非公平锁 5、ReentrantLock 扩展的功能 6
这份资源旨在详细讲解 Java 中的 Locks 框架,特别关注 ReentrantLock 的使用和原理。Locks 框架提供了比传统的 synchronized 关键字更强大、更灵活的线程同步机制,而 ReentrantLock 是其中的一种重要实现。 Locks ...
一张图将整个ReentrantLock流程看懂,干货满满 一张图将整个ReentrantLock流程看懂,干货满满 一张图将整个ReentrantLock流程看懂,干货满满 一张图将整个ReentrantLock流程看懂,干货满满 一张图将整个...
可重入锁: 也叫做递归锁,指的是同一线程 外层函数获得锁之后 ,...ReentrantLock 在Java也是一个基础的锁,ReentrantLock 实现Lock接口提供一系列的基础函数,开发人员可以灵活的是应用函数满足各种复杂多变应用场景;
1. ReentrantLock的介绍 ReentrantLock重入锁,是实现Lock接口的一个类,也是在实际编程中使用频率很高的一个锁,支持重入性,表示能够对共享资源能够重复加锁,即当前线程获取该锁再次获取不会被阻塞。在java...
ReentrantLock源码剖析
什么是公平锁和非公平锁 公平与非公平的一个很本质的区别就是,是否遵守FIFO(也就是先来后到)。当有多个线程来申请锁的时候,是否先申请的线程先获取锁,后申请的线程后获取锁?如果是的,则是 公平锁 ,否则是...
ReentrantLock类可以唤醒指定条件的线程,而object的唤醒是随机的 Condition类和Object类 Condition类的awiat方法和Object类的wait方法等效 Condition类的signal方法和Object类的notify方法等效 Condition类...
ReentrantLock 实现原理 1
使用ReentrantLock和Lambda表达式让同步更纯净Java开发Java经验技巧共5页.pdf.zip
ReentrantLock lock方法注释
Java多线程ReentrantLock1
AQS和ReentrantLock.pdf
ReentrantLock的基本用法 2.1 创建ReentrantLock 2.2 获取锁和释放锁 公平性与非公平性 3.1 公平锁 3.2 非公平锁 中断响应 条件变量与Condition 5.1 创建Condition 5.2 await()和signal() 可重入性 ReentrantLock与...
Lock、Synchoronized和ReentrantLock的使用
深入java并发编程,使用ReentrantLock和 Synchronized加锁
ReentrantLock 是JDK给我们提供的显示锁 在功能上远远强于synchronized 是功能上 不是性能上,随着JDK版本的一代又一代升级 synchronized的性能已经远远不是以前的重量级锁那么沉重 ReentrantLock源码 我们来看...