JUC并发编程基石AQS源码之结构篇-ReentrantLock
上篇文章JUC并发编程基石AQS源码之结构篇我们整体了解了JUC下加锁类的代码结构,这篇我们来看下ReentrantLock的代码结构,之后讲解AQS源码也主要以这个类为主。
实现Lock接口
首先是实现了Lock接口,实现了加锁方法lock(),但是这里没有直接调用AQS的acquire方法,往下看
public class ReentrantLock implements Lock, java.io.Serializable {public void lock() {sync.lock();}
定义内部类
先看一下内部类的继承关系,会发现比上一篇多了一层继承关系,我们来慢慢分析
定义了一个抽象内部类Sync继承了AQS,定义了一个抽象方法lock,但是会发现没有实现tryAcquire()方法,再往下看
public class ReentrantLock implements Lock, java.io.Serializable {abstract static class Sync extends AbstractQueuedSynchronizer {private static final long serialVersionUID = -5179523762034025860L;/*** Performs {@link Lock#lock}. The main reason for subclassing* is to allow fast path for nonfair version.*/abstract void lock();/*** Performs non-fair tryLock. tryAcquire is implemented in* subclasses, but both need nonfair try for trylock method.*/final boolean nonfairTryAcquire(int acquires) {final Thread current = Thread.currentThread();int c = getState();if (c == 0) {if (compareAndSetState(0, acquires)) {setExclusiveOwnerThread(current);return true;}}else if (current == getExclusiveOwnerThread()) {int nextc = c + acquires;if (nextc < 0) // overflowthrow new Error("Maximum lock count exceeded");setState(nextc);return true;}return false;}
又一个内部类NonfairSync实现了Sync,实现了Sync类的lock()方法,并且实现了tryAcquire方法。lock方法里调用了AQS的acquire()方法。
static final class NonfairSync extends Sync {private static final long serialVersionUID = 7316153563782823691L;/*** Performs lock. Try immediate barge, backing up to normal* acquire on failure.*/final void lock() {if (compareAndSetState(0, 1))setExclusiveOwnerThread(Thread.currentThread());elseacquire(1);}protected final boolean tryAcquire(int acquires) {return nonfairTryAcquire(acquires);}
}
到这我们就能梳理出大致的调用流程了,其中绿色部分代表需要自己实现
为什么多了一层结构?因为ReentrantLock有两种锁类型,公平锁和非公平锁
公平锁:不能插队,如果当前有线程在等待锁,则直接进入排队队列,等待在它之前排队的所有线程执行完后再去获取锁。
非公平锁:不管当前是否有其他线程在排队等待锁,先尝试获取一次锁,如果获取到则执行代码逻辑,否则进入排队队列,等待在它之前排队的所有线程执行完后再去获取锁。
而实现不同锁类型在代码上的体现就是对AQS的tryAcquire()方法的不同实现,有几种锁类型就有几个内部类。
再看上面这张图就会明白,NonfairSync代表了非公平锁的实现。FairSync代表了公平锁的实现。
加锁类型不同会有不同的tryAcquire()方法实现,其他的解锁等操作的逻辑是一致的,所以根据代码的重用性思想,就抽象出了Sync类。所以我们看Sync类只把加锁的方法抽象了,其他的都是具体的实现。
再看一下公平锁FairSync的代码,也只是实现了加锁的方法。
static final class FairSync extends Sync {private static final long serialVersionUID = -3000897897090466540L;final void lock() {acquire(1);}/*** Fair version of tryAcquire. Don't grant access unless* recursive call or no waiters or is first.*/protected final boolean tryAcquire(int acquires) {final Thread current = Thread.currentThread();int c = getState();if (c == 0) {if (!hasQueuedPredecessors() &&compareAndSetState(0, acquires)) {setExclusiveOwnerThread(current);return true;}}else if (current == getExclusiveOwnerThread()) {int nextc = c + acquires;if (nextc < 0)throw new Error("Maximum lock count exceeded");setState(nextc);return true;}return false;}
}
ReentrantLock默认的锁方式为非公平锁,构造方法中新建了NonfairSync的实例。所以在抽象类Sync默认给出了非公平锁的实现方法nonfairTryAcquire()。
//ReentrantLock构造方法
public ReentrantLock() {sync = new NonfairSync();
}
到此ReentrantLock类的结构我们大体都了解了,这样我们再去看源码才会有的放矢,知道为什么会跳到这个类的这个方法来执行了,这也是看懂AQS源码的第一个关键。
如有不实,还望指正
JUC并发编程基石AQS源码之结构篇-ReentrantLock相关推荐
- JUC并发编程02——AQS源码剖析
1.AQS介绍 相信每个Java Coder 都使用过或者至少听说过AQS, 它是抽象队列同步器AbstractQueuedSynchronizer 的简称,在juc包下.它提供了一套可用于实现锁同步 ...
- 并发编程之——读锁源码分析(解释关于锁降级的争议)
1. 前言 在前面的文章 并发编程之--写锁源码分析中,我们分析了 1.8 JUC 中读写锁中的写锁的获取和释放过程,今天来分析一下读锁的获取和释放过程,读锁相比较写锁要稍微复杂一点,其中还有一点有争 ...
- Java 并发编程 -- 线程池源码实战
一.概述 小编在网上看了好多的关于线程池原理.源码分析相关的文章,但是说实话,没有一篇让我觉得读完之后豁然开朗,完完全全的明白线程池,要么写的太简单,只写了一点皮毛,要么就是是晦涩难懂,看完之后几乎都 ...
- 3000门徒内部训练绝密视频(泄密版)第5课:彻底精通Scala隐式转换和并发编程及Spark源码阅读
彻底精通Scala隐式转换和并发编程及Spark源码阅读 Akka ,Scala内部并发 隐式转换.隐式类.隐式参数 可以手动指定某种类型的对象或类转换成其他类型的对象或类.转换的原因是假设写好接口 ...
- java线程池_Java 并发编程 线程池源码实战
作者 | 马启航 杏仁后端工程师.「我头发还多,你们呢?」 一.概述 笔者在网上看了好多的关于线程池原理.源码分析相关的文章,但是说实话,没有一篇让我觉得读完之后豁然开朗,完完全全的明白线程池,要么写 ...
- Java并发编程:从源码分析几道必问线程池的面试题?
引言 上一篇文章我们有介绍过线程池的一个基本执行流程<[Java并发编程]面试必备之线程池>以及它的7个核心参数,以及每个参数的作用.以及如何去使用线程池 还留了几个小问题..建议看这篇文 ...
- 并发编程之——写锁源码分析
1.前言 Java 中的读写锁实现是 ReentrantReadWriteLock ,是一种锁分离策略.能有效提高读比写多的场景下的程序性能. 关于如何使用参见 并发编程之 Java 三把锁. 由于读 ...
- 29W 字总结阿里 Java 高并发编程:案例 + 源码 + 面试 + 系统架构设计
下半年的跳槽季已经开始,好多同学已经拿到了不错的 Offer,同时还有一些同学对于 Java 高并发编程还缺少一些深入的理解,不过不用慌,今天老师分享的这份 27W 字的阿里巴巴 Java 高并发编程 ...
- Go 并发编程Mutex(二)--源码
文章目录 1. 初版的互斥锁 2. 给新人机会 3. 多给些机会 4. 解决饥饿 5. 饥饿模式和正常模式 6. 总结 一讲我们一起体验了 Mutex 的使用,竟是那么简单,只有简简单单两个方法,Lo ...
- 多线程高并发编程(10) -- ConcurrentHashMap源码分析
一.背景 前文讲了HashMap的源码分析,从中可以看到下面的问题: HashMap的put/remove方法不是线程安全的,如果在多线程并发环境下,使用synchronized进行加锁,会导致效率低 ...
最新文章
- boost::math::quadrature::trapezoidal用法的测试程序
- 安卓logcat工具apk_backdoorapk 安卓APK后门捆绑脚本
- Day 5内存管理,定义变量
- etc fstab 详解linux,/etc/fstab文件详解
- ROS中的AGV与ROS_CONTROL学习
- 无法连接阿里云 Windows 实例远程桌面
- 怎样把计算机里的W0rd放到电脑桌面,当电脑桌面没有WORD文档时怎么打开WORD文档...
- 网页游戏外挂辅助AMF模拟通讯必备
- 【计算机图形学】小白谈计算机图形学(五)
- adb 连接安卓手机远程调试
- 美国程序员薪水按编程语言大比拼新浪
- rpcx服务框架浅析9-序列化
- 哈工大计算机854考研经验分享
- ESB项目培训样例说明
- 汇编中的test和cmp指令[Z]
- jquery 线上 引用地址
- Scratch简单实现大鱼吃小鱼
- 算法的特性和设计要求
- python判断循环小数_python如果一个数是为无限循环小数,返回分数格式,否则返回小数格式...
- 2021年清远高考成绩查询,2021年清远高考状元是谁分数多少分,历年清远高考状元名单...
热门文章
- allt什么意思_all是什么意思_all怎么读_all翻译_用法_发音_词组_同反义词_全部的-新东方在线英语词典...
- python做小游戏之一小迷宫游戏
- 七、torch.nn
- 购物系统 java代码_java购物系统源代码
- L1-7 机工士姆斯塔迪奥 (20 分),C语言
- 什么是绝对URL、相对URL
- 2_PY基本数据类型
- allure-report详细使用教程
- VMware ESXi/ESX 的内部版本号和版本 (2143832)
- 【有奖倒计时】带你走进AI应用创新大赛十强背后的故事!