ReentrantLock是如何实现可重入性

简介: ReentrantLock是如何实现可重入性

1 问题

ReentrantLock是如何实现可重入性的?并且在进入锁内之前进行了哪些判断?


2 方法

// Sync继承于AQS
abstract static class Sync extends AbstractQueuedSynchronizer {
...
}
// ReentrantLock默认是非公平锁
public ReentrantLock() {
       sync = new NonfairSync();
}
// 可以通过向构造方法中传true来实现公平锁
public ReentrantLock(boolean fair) {
   sync = fair ? new FairSync() : new NonfairSync();
}
protected final boolean tryAcquire(int acquires) {
       // 当前想要获取锁的线程
       final Thread current = Thread.currentThread();
       // 当前锁的状态
       int c = getState();
       // state == 0 此时此刻没有线程持有锁
       if (c == 0) {
           // 虽然此时此刻锁是可以用的,但是这是公平锁,既然是公平,就得讲究先来后到,
           // 看看有没有别人在队列中等了半天了
           if (!hasQueuedPredecessors() &&
               // 如果没有线程在等待,那就用CAS尝试一下,成功了就获取到锁了,
               // 不成功的话,只能说明一个问题,就在刚刚几乎同一时刻有个线程抢先了 =_=
               // 因为刚刚还没人的,我判断过了
               compareAndSetState(0, acquires)) {
               // 到这里就是获取到锁了,标记一下,告诉大家,现在是我占用了锁
               setExclusiveOwnerThread(current);
               return true;
           }
       }
         // 会进入这个else if分支,说明是重入了,需要操作:state=state+1
       // 这里不存在并发问题
       else if (current == getExclusiveOwnerThread()) {
           int nextc = c + acquires;
           if (nextc < 0)
               throw new Error("Maximum lock count exceeded");
           setState(nextc);
           return true;
       }
       // 如果到这里,说明前面的if和else if都没有返回true,说明没有获取到锁
       return false;
   }


3 结语

ReentrantLock使用内部类Sync来管理锁,所以真正的获取锁是由Sync的实现类控制的。在进行前先判断锁内是否有数据,没有锁就选择Sync继承AQS来实现进入锁内;如果锁内有数据则先判断数据是否是自己的,是自己的数据就将state的值+1,表示重入。

目录
相关文章
|
SQL 消息中间件 分布式计算
12中方法,彻底搞定数据倾斜!
12中方法,彻底搞定数据倾斜!
|
Shell Linux Docker
Docker -v 挂载主机目录到容器中(及数据卷容器)
Docker -v 挂载主机目录到容器中(及数据卷容器)
2477 0
|
12月前
|
存储 缓存 安全
内存屏障,写屏障和读屏障
本文介绍了Java内存模型(JMM)的关键概念,包括主内存、工作内存、原子性操作、可见性和有序性,并详细解释了写屏障和读屏障的作用,它们是用来确保多线程环境中内存可见性和指令重排序一致性的同步操作。
328 1
|
12月前
|
XML JavaScript Java
BeanFactory 和 FactoryBean的区别
本文介绍了Spring框架中的`BeanFactory`和`FactoryBean`。`BeanFactory`是Spring的核心接口,用于管理Bean的创建、配置及依赖注入。其实现包括`DefaultListableBeanFactory`和已废弃的`XmlBeanFactory`。`FactoryBean`则用于动态创建Bean实例,支持懒加载及AOP代理创建。文章还通过示例展示了如何实现一个`FactoryBean`,并通过测试验证其功能。最后附上了作者信息及版权声明。
411 0
BeanFactory 和 FactoryBean的区别
|
缓存 前端开发 JavaScript
终极 Nginx 配置指南(全网最详细)
本文详细介绍了Nginx配置文件`nginx.conf`的基本结构及其优化方法。首先通过删除注释简化了原始配置,使其更易理解。接着,文章将`nginx.conf`分为全局块、events块和http块三部分进行详细解析,帮助读者更好地掌握其功能与配置。此外,还介绍了如何通过简单修改实现网站上线,并提供了Nginx的优化技巧,包括解决前端History模式下的404问题、配置反向代理、开启gzip压缩、设置维护页面、在同一IP上部署多个网站以及实现动静分离等。最后,附上了Nginx的基础命令,如安装、启动、重启和关闭等操作,方便读者实践应用。
5235 85
终极 Nginx 配置指南(全网最详细)
|
10月前
|
缓存 Java 测试技术
分享干货:idea常用快捷键分类总结(适合速查~~建议收藏♥)
本文以分类的形式总结了IDEA常用、好用快捷键,全是干货~
2585 1
分享干货:idea常用快捷键分类总结(适合速查~~建议收藏♥)
|
存储 关系型数据库 MySQL
为什么MySQL索引使用B+树而不用hash表和B树
支持范围查询:B+树索引在数据结构上有序排列,可以有效支持范围查询,例如大于、小于、区间查询等操作。而哈希表无法支持范围查询,只能进行精确查找,而B树在范围查询操作时性能相对较低。
579 0
|
存储 数据库 数据格式
深入理解依赖倒置原则(Dependence Inversion Principle)
深入理解依赖倒置原则(Dependence Inversion Principle)
1039 0
|
存储 NoSQL 算法
分布式唯一 ID 的 7 种生成方案
在互联网的业务系统中,涉及到各种各样的ID,如在支付系统中就会有支付ID、退款ID等。那一般生成ID都有哪些解决方案呢?特别是在复杂的分布式系统业务场景中,我们应该采用哪种适合自己的解决方案是十分重要的。下面我们一一来列举一下,不一定全部适合,这些解决方案仅供你参考,或许对你有用。
分布式唯一 ID 的 7 种生成方案
|
机器学习/深度学习 传感器 编解码
【多传感器融合】BEVFusion: 激光雷达和摄像头融合框架 NeurIPS 2022
BEVFusion提出一个融合多摄像头和激光雷达数据的框架,可用于3D检测。在自动驾驶领域,通过独立处理并融合摄像头和激光雷达数据,可以显著提升3D对象检测的准确性和稳健性,尤其是在激光雷达可能出现故障的真实场景中。
3522 57
【多传感器融合】BEVFusion: 激光雷达和摄像头融合框架 NeurIPS 2022