从ReentrantLock加锁解锁角度分析AQS
本文用于记录在学习AQS时,以ReentrantLock为切入点,深入源码分析ReentrantLock的加锁和解锁过程。
同步器AQS的主要使用方式是继承,子类通过继承同步器并实现它的抽象方法来管理同步状态(通常锁或者同步组件内部会实现一个Sync类(该类是一个静态内部类),然后让Sync类去继承AQS类,通过继承AQS队列同步器并实现它的抽象方法来管理同步状态),对同步状态进行更改需要使用同步器提供的3个方法 getState、setState 和 compareAndSetState ,它们保证状态改变是安全的。
下图是ReentrantLock中所有的内部类和方法:

3个内部类之间的关系如下图所示:

以ReentrantLock为例,从源码分析如何进行加锁和解锁。
ReentrantLock lc = new ReentrantLock();
lc.lock();
lc.unlock();
(1)ReentrantLock构造函数(为了方便分析,我们以非公平队列为例子)

(2)lc.lock()

ReentrantLock类中的lock()方法调用sync实例中的lock()方法,因为我们是以非公平队列为例子,所以此时的sync实例的类型为NonfairSync。即调用NonfairSync.lock()

紧接着进入209行对应的acquire(1)方法:该方法位于AQS框架中,且被final修饰,即不能被子类重写。

紧接着进入tryAcquire(int arg)方法

我们发现AQS中的tryAcquire(int arg)方法中没有实现体,说明tryAcquire(int arg)方法需要AQS子类实现,根据上面的继承图可知,Sync以及NonfairSync都是AQS的子类,由下图可知,tryAcquire(int arg)方法的实现位于NonfairSync内部类中

进入NonfairSync内部类中的ryAcquire(int arg)方法可以发现其调用了Sync静态内部类中的nonfairTryAcquire方法。


至此成功获取了锁。
(1) 通过ReentrantLock的加锁方法Lock进行加锁操作。
(2) 会调用到内部类Sync的Lock方法,根据ReentrantLock初始化选择的公平锁和非公平锁,执行相关内部类的Lock方法,本质上都会执行AQS的acquire方法。
(3) AQS的Acquire方法会执行tryAcquire方法,但是由于tryAcquire需要自定义同步器实现,因此执行了ReentrantLock中的tryAcquire方法,由于ReentrantLock是通过公平锁和非公平锁内部类实现的tryAcquire方法,因此会根据锁类型不同,执行不同的tryAcquire。
(4) tryAcquire是获取锁逻辑,获取失败后,会执行框架AQS的后续逻辑,跟ReentrantLock自定义同步器无关。
(3)lc.unlock()
释放锁的过程和加锁过程类似,不走进源码,直接上文字版流程
(1) 通过ReentrantLock的解锁方法Unlock进行解锁。
(2) Unlock会调用内部类Sync的release方法,该方法继承于AQS。
(3) release中会调用tryRelease方法,tryRelease需要自定义同步器实现,tryRelease只在ReentrantLock中的Sync实现,因此可以看出,释放锁的过程,并不区分是否为公平锁。
(4) 释放成功后,所有处理由AQS框架完成,与自定义同步器无关。
经过上述的学习,可以归纳总结出如果要自定义一个同步组件,可以按照如下步骤
- 第一步:内部写一个Sync类继承
AbstractQueuedSynchronizer接口。 - 第二步:根据是否独占来重写队列同步器中的方法,如果需要独占则实现
tryAcquire()/tryRelease()等方法,如果不需要独占,则实现tryAcquireShared(int acquires)和tryReleaseShared(int releases)等方法。 - 第三步:初始化Sync对象,并在锁的获取/释放方法(通常为lock()以及unlock()方法)中调用AQS的
acquire()/release()或者acquireShared()/releaseShared()方法。
从ReentrantLock加锁解锁角度分析AQS的更多相关文章
- 透过 ReentrantLock 分析 AQS 的实现原理
对于 Java 开发者来说,都会碰到多线程访问公共资源的情况,这时候,往往都是通过加锁来保证访问资源结果的正确性.在 java 中通常采用下面两种方式来解决加锁得问题: synchronized 关键 ...
- java多线程系列(五)---synchronized ReentrantLock volatile Atomic 原理分析
java多线程系列(五)---synchronized ReentrantLock volatile Atomic 原理分析 前言:如有不正确的地方,还望指正. 目录 认识cpu.核心与线程 java ...
- 从开发者的角度分析iOS应如何省电
从开发者的角度分析iOS应如何省电 说明 网上关于iPhone如何省电的文章很多.但是基本没有讲原理.而在生活中,很多人在使用iPhone中有着明显的错误的省电习惯. 本文从iOS开发者的角度,对iO ...
- 进程间通信(IPC)+进程加锁解锁
[0]README 0.1) source code and text description are from orange's implemention of a os: 0.2) for com ...
- 源码角度分析-newFixedThreadPool线程池导致的内存飙升问题
前言 使用无界队列的线程池会导致内存飙升吗?面试官经常会问这个问题,本文将基于源码,去分析newFixedThreadPool线程池导致的内存飙升问题,希望能加深大家的理解. (想自学习编程的小伙伴请 ...
- Linux 进程与线程四(加锁--解锁)
线程共享进程的内存空间,打开的文件描述符,全局变量. 当有多个线程同事访问一块内存空间或者一个变量.一个文件描述符,如果不加控制,那么可能会出现意想不到的结果. 原子操作 对于我们的高级语言(C语言, ...
- Android IOS WebRTC 音视频开发总结(六六)-- 三个角度分析美女视频直播这个行业
本文主要从用户,公司和技术角度分析美女视频直播这个行业,文章最早发表在我们的微信公众号上,支持原创,详见这里, 欢迎关注微信公众号blackerteam,更多详见www.rtc.help 美女视频直播 ...
- 从源码的角度分析ViewGruop的事件分发
从源码的角度分析ViewGruop的事件分发. 首先我们来探讨一下,什么是ViewGroup?它和普通的View有什么区别? 顾名思义,ViewGroup就是一组View的集合,它包含很多的子View ...
- 从不同的角度分析Flex的优缺点
从不同的角度分析Flex的优缺点 技术角度: (1)具备了RIA时代富客户端的优点(C/S+B/S) (2)支持多种服务器语言(JAVA..NET.PHP)及主流框架(Spring.Hibernate ...
随机推荐
- 2.1 java语言概述
链接:https://pan.baidu.com/s/1ab2_KapIW-ZaT8kedNODug 提取码:miao
- 多线程循环打印数组 -- Java笔记
问题描述: 现有多个长度相同的数组,现要求使用多线程将数组内的数交替打印. 如: int[] ai = {1,2,3,4,5,6,7}; String[] ac = {"A",&q ...
- matlab中find 查找非零元素的索引和值
来源:https://ww2.mathworks.cn/help/matlab/ref/find.html?searchHighlight=find&s_tid=doc_srchtitle f ...
- [学习笔记] Tarjan算法求桥和割点
在之前的博客中我们已经介绍了如何用Tarjan算法求有向图中的强连通分量,而今天我们要谈的Tarjan求桥.割点,也是和上篇有博客有类似之处的. 关于桥和割点: 桥:在一个有向图中,如果删去一条边,而 ...
- 从字节码层次看i++和++i
关于的Java的i++和++i的区别,初学者可能会混淆,这时候有经验的同学或同事就会告诉你,++在后,就会立马加值, ++在后则会等会儿再加,所以如果i == 0 ,那么i++ == 0,++i == ...
- 玩转控件:GDI+动态绘制流程图
前言 今天,要跟大家一起分享是"GDI+动态生成流程图"的功能.别看名字高大上(也就那样儿--!),其实就是动态生成控件,然后GDI+绘制直线连接控件罢了.实际项目效果图如下 ...
- Python:MySQL数据库环境相关问题
系统环境 Ubuntu 16.04.2 LTS mysql Ver 14.14 Distrib 5.7.18, for Linux (x86_64) using EditLine wrapper P ...
- 远程IO
远程io 远程io ZLAN6842,ZLAN6844是8路远程O控制器.含有8路DI.8路DO,8路AI输入.其中DI支持干节点和湿节点,带光耦隔离:DO为继电器输出,具有5A 250VAC或5A ...
- day36 Pyhton 网络编程03
一.内容回顾 socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. sock ...
- shell携带附件,Linux下的自解压文件诞生了
初衷 windows下有自解压文件,直接双击就能释放文件,并且还能执行释放文件前后要执行的脚本.Linux下我也想要这样的功能,因为我希望直接拷贝一个shell脚本给别人,别人直接运行就能用,而不是一 ...