本文用于记录在学习AQS时,以ReentrantLock为切入点,深入源码分析ReentrantLock的加锁和解锁过程。

同步器AQS的主要使用方式是继承,子类通过继承同步器并实现它的抽象方法来管理同步状态(通常锁或者同步组件内部会实现一个Sync类(该类是一个静态内部类),然后让Sync类去继承AQS类,通过继承AQS队列同步器并实现它的抽象方法来管理同步状态),对同步状态进行更改需要使用同步器提供的3个方法 getStatesetStatecompareAndSetState ,它们保证状态改变是安全的。

下图是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的更多相关文章

  1. 透过 ReentrantLock 分析 AQS 的实现原理

    对于 Java 开发者来说,都会碰到多线程访问公共资源的情况,这时候,往往都是通过加锁来保证访问资源结果的正确性.在 java 中通常采用下面两种方式来解决加锁得问题: synchronized 关键 ...

  2. java多线程系列(五)---synchronized ReentrantLock volatile Atomic 原理分析

    java多线程系列(五)---synchronized ReentrantLock volatile Atomic 原理分析 前言:如有不正确的地方,还望指正. 目录 认识cpu.核心与线程 java ...

  3. 从开发者的角度分析iOS应如何省电

    从开发者的角度分析iOS应如何省电 说明 网上关于iPhone如何省电的文章很多.但是基本没有讲原理.而在生活中,很多人在使用iPhone中有着明显的错误的省电习惯. 本文从iOS开发者的角度,对iO ...

  4. 进程间通信(IPC)+进程加锁解锁

    [0]README 0.1) source code and text description are from orange's implemention of a os: 0.2) for com ...

  5. 源码角度分析-newFixedThreadPool线程池导致的内存飙升问题

    前言 使用无界队列的线程池会导致内存飙升吗?面试官经常会问这个问题,本文将基于源码,去分析newFixedThreadPool线程池导致的内存飙升问题,希望能加深大家的理解. (想自学习编程的小伙伴请 ...

  6. Linux 进程与线程四(加锁--解锁)

    线程共享进程的内存空间,打开的文件描述符,全局变量. 当有多个线程同事访问一块内存空间或者一个变量.一个文件描述符,如果不加控制,那么可能会出现意想不到的结果. 原子操作 对于我们的高级语言(C语言, ...

  7. Android IOS WebRTC 音视频开发总结(六六)-- 三个角度分析美女视频直播这个行业

    本文主要从用户,公司和技术角度分析美女视频直播这个行业,文章最早发表在我们的微信公众号上,支持原创,详见这里, 欢迎关注微信公众号blackerteam,更多详见www.rtc.help 美女视频直播 ...

  8. 从源码的角度分析ViewGruop的事件分发

    从源码的角度分析ViewGruop的事件分发. 首先我们来探讨一下,什么是ViewGroup?它和普通的View有什么区别? 顾名思义,ViewGroup就是一组View的集合,它包含很多的子View ...

  9. 从不同的角度分析Flex的优缺点

    从不同的角度分析Flex的优缺点 技术角度: (1)具备了RIA时代富客户端的优点(C/S+B/S) (2)支持多种服务器语言(JAVA..NET.PHP)及主流框架(Spring.Hibernate ...

随机推荐

  1. matlab中axis的用法

    来源:https://ww2.mathworks.cn/help/matlab/ref/axis.html?searchHighlight=axis&s_tid=doc_srchtitle a ...

  2. P5664 Emiya 家今天的饭

    题面 link 前言 去年把我做自闭的一道题,看了一眼题面,发现只有 t1 有点思路,结果写到一半发现自己读错题了,又只能花时间来重构,结果后面的暴力一点都没写(主要是自己当时不会) 然后,这道题还因 ...

  3. 正式班D5

    2020.10.10星期六 正式班D5 一.上节课复习 1.硬盘分类 ​ 1.机械磁盘 ​ io时间=平均寻道时间+平均延迟时间 ​ buffer:写缓冲区 ​ cache:都缓存 ​ 2.固态硬盘 ...

  4. 扩展、接管MVC都不会,还会用Spring Boot?

    持续原创输出,点击上方蓝字关注我 目录 前言 Spring Boot 版本 如何扩展MVC? 如何自定义一个拦截器? 什么都不配置为什么依然能运行MVC相关的功能? 如何全面接管MVC?[不推荐] 为 ...

  5. fastadmin 增加批量操作字段 提示无权限

    是这样的找了权限节点的问题,始终找不到,后来 在社区传世人回答别人问题是提及到  $multiFields 就全局搜了下 在基类 Backend 里找到了这个.然后拿到 控制器中添加需要的参数 再次尝 ...

  6. 1.Linux内核模块编程

    1.模块加载程序结构 - 模块加载函数: static int _init init_function(void); module_init(init_function); - 模块卸载函数: sta ...

  7. python虚拟环境的配置-ubuntu 18.04后

    python虚拟环境的配置 安装相关包 pip install virtualenv pip install virtualenvwrapper 配置~/.bashrc 加入以下内容: ------- ...

  8. jmeter_02_目录文档说明

    jmeter目录文档说明 bin目录是可执行文件 jmeter.bat 是启动文件 可以启动jmeter. 使用notpad++ 等文本编辑器打开 bat文件 可以配置jvm的参数 比如堆内存[Hea ...

  9. 【原创】有利于提高xenomai 实时性的一些配置建议

    版权声明:本文为本文为博主原创文章,转载请注明出处.如有错误,欢迎指正. @ 目录 一.影响因素 1.硬件 2.BISO(X86平台) 3.软件 4. 缓存使用策略与GPU 二.优化措施 1. BIO ...

  10. centos8平台redis5的主从同步搭建及sentinel哨兵配置

    一,规划三台redis的ip:一主二从 redismaster01: 172.18.1.1 主 redisslave01: 172.18.1.2 从 redisslave02: 172.18.1.3 ...