JDK 学习日记 - AbstractQueuedSynchronizer

背景

AbstractQueuedSynchronizer 简称 AQS 是 JDK 中 JUC 包的核心方法。包括 ReentrantLock , Semaphore , CountDownLoatch 甚至是 ThreadPoolExectur 中的 Worker 都是基于其实现的。可以说搞明白了 AQS 就搞懂了 JUC。

AQS 做了什么

AQS 提供了一个基于 FIFO 的快速实现阻塞锁的框架。

为什么要 AQS

我们知道在 Java 中有一个关键字 synchronized 已经用于同步,并且随着 JDK 的不断迭代, synchronized 已经拥有了较好的性能,既然这样,为什么还会需要 AQS 呢。

synchronized 的局限性

虽然 synchronized 已经能有很好性能的,但是 synchronized 底层其实还是基于一个 CAS 的自旋操作,也就是说 synchronized 其实是个自旋锁。当处于高并发的环境之中,这会导致极强的锁竞争,大量的自旋操作,会极大的浪费计算资源。所以 synchronized 在高并发的场景并不是特别好。

注: 虽然我们知道 synchronized 做了很多优化,但是那些偏向锁,轻量级锁的优化,归根结底都是加速当前
并发量较小,我们该怎么设计,让锁占用更少的系统资源。相关文章参考 [Java 并发编程: 核心理论]
(http://www.cnblogs.com/paddix/p/5374810.html) 

AQS 的优势

既然讲到了 synchronized 的局限性,自然要讲讲 AQS 的优势。 AQS 的主要优势有两点

一: 提供更丰富的 API

基于 AQS 的 ReentrantLock, Semaphore 等相比于 synchronized 提供了更为丰富的 API 接口,也就是提供了更为丰富更强大的功能。

二: 挂起线程,更适合高并发场景

AQS 内部改造的 CLH 队列,在一定条件下会将没有获取锁的线程挂起,等到锁被释放后再唤起,这样就保证了在高并发的场景下,不会有太多的线程竞争资源,而是大部分都在等待被唤醒,减少了性能的损耗。

AQS 实现原理

AQS 的实现,主要依赖两个部分,第一个改造的 CLH 队列,另一个是 LockSupport 线程挂起方法。首先我们介绍一下标准的 CLH 队列,然后我们再聊 AQS 中改造的 CLH 队列。

CLH 队列

CLH 队列其实很简单,CLH 队列其实就是一个链表,链表的每个节点有一个 isLocked 字段,该字段标明当前是否需要持有锁。以及一个 prev 指针,指向前置节点。

CLH 入队列获取锁

当一个线程要获取锁的时候,会先入队列尾部,然后读取前置节点的 isLocked 字段,如果该字段为 false ,则不断自旋读取 isLocked 字段,直到 isLocked 为 true,则表示当前线程获取锁成功。

CLH 出队列释放锁

当线程释放锁之后,会将自身的节点出队列,然后将自身节点的 isLocked 字段置为 true,让后继节点获取锁。

CLH 执行过程

以上就是标准 CLH 队列的实现方式。

LockSupport 方法

标准 CLH 队列实现非常简单, 但是仔细一看会发现,其实 CLH 队列也是一个自旋方式控制获取锁同步的方案。如果直接使用 CLH 队列其实和 synchronized 没有太大的区别。所以这个时候 LockSupport 出场了!!!当!当!当!当!

LockSupport 内部有两个关键方法,分别为

public static void unpark(Thread thread) {
        if (thread != null)
            UNSAFE.unpark(thread);
    }
public static void park(Object blocker) {
        Thread t = Thread.currentThread();
        setBlocker(t, blocker);
        UNSAFE.park(false, 0L);
        setBlocker(t, null);
    }

其中 park 方法用于挂起线程,这样除非线程重新被唤醒,否则线程将不会再占用操作系统计算资源,自然地,unpark 方法就是用于唤醒被挂起的线程。

AQS 实现原理概述

有了上述 CLH 和 LockSupprt 的讲述,那么 AQS 如何实现就很明显了。

  • 首先 AQS 中维护了一个 CLH 队列,不过不同于标准的 CLH 队列,AQS 中 CLH 队列,当前置节点中的状态表明的是当前可以获取锁,而不是表示获取锁成功。同样的释放锁也类似。

  • 第二,对于获取锁失败的线程,不是自旋地等待,而是主动挂起,然后当前一个节点释放锁的时候,需要主动的释放下一个线程。

其它

为什么要队列

因为有挂起和唤醒的过程,所以需要能记录被挂起的线程,这是为什么要队列的原因。

为什么是 CLH 队列

其实同步锁除了 CLH 队列之外,还有一个 MCS 队列,之所以要用 CLH 队列主要是相对于 MCS 队列来说,CLH 队列更容易取消和实现超时控制。MCS 队列和 CLH 队列的区别仅仅在于线程是自旋自身节点的 isLocked,而不是自旋前置节点的 isLocked。参考 A Hierarchical CLH Queue Lock

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。、可私 6信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 、可私信6博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 、可私信6博主看论文后选择购买源代码。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值