上篇文章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相关推荐

  1. JUC并发编程02——AQS源码剖析

    1.AQS介绍 相信每个Java Coder 都使用过或者至少听说过AQS, 它是抽象队列同步器AbstractQueuedSynchronizer 的简称,在juc包下.它提供了一套可用于实现锁同步 ...

  2. 并发编程之——读锁源码分析(解释关于锁降级的争议)

    1. 前言 在前面的文章 并发编程之--写锁源码分析中,我们分析了 1.8 JUC 中读写锁中的写锁的获取和释放过程,今天来分析一下读锁的获取和释放过程,读锁相比较写锁要稍微复杂一点,其中还有一点有争 ...

  3. Java 并发编程 -- 线程池源码实战

    一.概述 小编在网上看了好多的关于线程池原理.源码分析相关的文章,但是说实话,没有一篇让我觉得读完之后豁然开朗,完完全全的明白线程池,要么写的太简单,只写了一点皮毛,要么就是是晦涩难懂,看完之后几乎都 ...

  4. 3000门徒内部训练绝密视频(泄密版)第5课:彻底精通Scala隐式转换和并发编程及Spark源码阅读

    彻底精通Scala隐式转换和并发编程及Spark源码阅读 Akka ,Scala内部并发 隐式转换.隐式类.隐式参数 可以手动指定某种类型的对象或类转换成其他类型的对象或类.转换的原因是假设写好接口 ...

  5. java线程池_Java 并发编程 线程池源码实战

    作者 | 马启航 杏仁后端工程师.「我头发还多,你们呢?」 一.概述 笔者在网上看了好多的关于线程池原理.源码分析相关的文章,但是说实话,没有一篇让我觉得读完之后豁然开朗,完完全全的明白线程池,要么写 ...

  6. Java并发编程:从源码分析几道必问线程池的面试题?

    引言 上一篇文章我们有介绍过线程池的一个基本执行流程<[Java并发编程]面试必备之线程池>以及它的7个核心参数,以及每个参数的作用.以及如何去使用线程池 还留了几个小问题..建议看这篇文 ...

  7. 并发编程之——写锁源码分析

    1.前言 Java 中的读写锁实现是 ReentrantReadWriteLock ,是一种锁分离策略.能有效提高读比写多的场景下的程序性能. 关于如何使用参见 并发编程之 Java 三把锁. 由于读 ...

  8. 29W 字总结阿里 Java 高并发编程:案例 + 源码 + 面试 + 系统架构设计

    下半年的跳槽季已经开始,好多同学已经拿到了不错的 Offer,同时还有一些同学对于 Java 高并发编程还缺少一些深入的理解,不过不用慌,今天老师分享的这份 27W 字的阿里巴巴 Java 高并发编程 ...

  9. Go 并发编程Mutex(二)--源码

    文章目录 1. 初版的互斥锁 2. 给新人机会 3. 多给些机会 4. 解决饥饿 5. 饥饿模式和正常模式 6. 总结 一讲我们一起体验了 Mutex 的使用,竟是那么简单,只有简简单单两个方法,Lo ...

  10. 多线程高并发编程(10) -- ConcurrentHashMap源码分析

    一.背景 前文讲了HashMap的源码分析,从中可以看到下面的问题: HashMap的put/remove方法不是线程安全的,如果在多线程并发环境下,使用synchronized进行加锁,会导致效率低 ...

最新文章

  1. boost::math::quadrature::trapezoidal用法的测试程序
  2. 安卓logcat工具apk_backdoorapk 安卓APK后门捆绑脚本
  3. Day 5内存管理,定义变量
  4. etc fstab 详解linux,/etc/fstab文件详解
  5. ROS中的AGV与ROS_CONTROL学习
  6. 无法连接阿里云 Windows 实例远程桌面
  7. 怎样把计算机里的W0rd放到电脑桌面,当电脑桌面没有WORD文档时怎么打开WORD文档...
  8. 网页游戏外挂辅助AMF模拟通讯必备
  9. 【计算机图形学】小白谈计算机图形学(五)
  10. adb 连接安卓手机远程调试
  11. 美国程序员薪水按编程语言大比拼新浪
  12. rpcx服务框架浅析9-序列化
  13. 哈工大计算机854考研经验分享
  14. ESB项目培训样例说明
  15. 汇编中的test和cmp指令[Z]
  16. jquery 线上 引用地址
  17. Scratch简单实现大鱼吃小鱼
  18. 算法的特性和设计要求
  19. python判断循环小数_python如果一个数是为无限循环小数,返回分数格式,否则返回小数格式...
  20. 2021年清远高考成绩查询,2021年清远高考状元是谁分数多少分,历年清远高考状元名单...

热门文章

  1. allt什么意思_all是什么意思_all怎么读_all翻译_用法_发音_词组_同反义词_全部的-新东方在线英语词典...
  2. python做小游戏之一小迷宫游戏
  3. 七、torch.nn
  4. 购物系统 java代码_java购物系统源代码
  5. L1-7 机工士姆斯塔迪奥 (20 分),C语言
  6. 什么是绝对URL、相对URL
  7. 2_PY基本数据类型
  8. allure-report详细使用教程
  9. VMware ESXi/ESX 的内部版本号和版本 (2143832)
  10. 【有奖倒计时】带你走进AI应用创新大赛十强背后的故事!