专栏首页JVMGCJava并发J.U.C 之 AQS
原创

Java并发J.U.C 之 AQS

J.U.C 之 AQS

AbStractQueuedSynchronizer类,简称AQS,是一个来构建锁和同步器的框架,JDK1.5开始引入了J.U.C,大大提高了JAVA程序的并发性,而AQS则是J.U.C的核心,是并发类中的核心部分,他是一个基于FIFO队列,这个队列可以构建锁或其它相关的同步基础框架

AQS底层结构

image-20210111211406234

底层采用双向链表,是队列的一种实现,因此可以当做是一个队列。其中Sync queue即同步队列,它是双向链表,包括hean结点(主要用作后续的调度)与tail结点。Condition queue不是必须的,单向链表,只有在需要使用到condition的时候才会存在这个单向链表,并且可能存在多个Condition queue

  • 使用Node实现FIFO队列,可以用于构建锁或者其他同步装置的基础框架
  • 利用了一个int类型表示状态。在AQS中,存在一个state成员变量,基于AQS有一个同步组件ReentrantLock,在这个组件中,state表示获取锁的线程数,假如state == 0表示无线程获取锁,state == 1表示已有线程获取锁,state > 1表示锁的数量
  • 使用方法是继承。AQS的设计是基于模板方法,使用需要继承AQS,并覆写其中的方法。
  • 子类通过继承并通过实现它的方法管理其状态{acquire() 和 release()}的方法操纵状态
  • 可以同时实现排它锁和共享锁模式(独占、共享)。它的所有子类中,要么实现并使用它的独占功能API,要么实现共享锁的功能,而不会同时使用两套API。即便是它比较有名的子类ReentrantReadWirteLock也是通过两个内部类读锁和写锁分别使用两套API实现的。AQS在功能上,有独占控制和共享控制两种功能。
  • 在LOCK包中的相关锁(常用的有ReentrantLock、 ReadWriteLock)都是基于AQS来构建.然而这些锁都没有直接来继承AQS,而是定义了一个Sync类去继承AQS,因为锁面向的是使用用户,而同步器面向的则是线程控制,那么在锁的实现中聚合同步器而不是直接继承AQS就可以很好的隔离二者所关注的事情.

基于以上设计,AQS具体实现的大致思路

AQS内部维护了一个CLH队列来管理锁,线程首先会尝试获取锁,如果失败,会将当前线程以及等待状态等信息包装成Node结点加入同步队列(Sync queue)中。接着不断循环尝试获取锁,条件是当前结点为head直接后继才会尝试,如果失败则会阻塞自己,直到自己被唤醒;而当持有锁的线程,释放锁的时候,会唤醒队列中后继线程。基于这些基础的设计和思路,JDK提供了许多基于AQS的子类。

独占式锁过程总结

AQS的模板方法acquire通过调用子类自定义实现的tryAcquire获取同步状态失败后->将线程构造成Node节点(创建一个独占式节点 )(addWaiter)->将Node节点添加到同步队列对尾(addWaiter)->节点以自旋的方法获取同步状态(acquirQueued)。在节点自旋获取同步状态时,只有其前驱节点是头节点的时候才会尝试获取同步状态,如果该节点的前驱不是头节点或者该节点的前驱节点是头节点单获取同步状态失败,则判断当前线程需要阻塞,如果需要阻塞则需要被唤醒过后才返回。在释放同步状态时,同步器调用tryRelease(int arg)方法释放同步状态,然后唤醒头节点的后继节点。

共享式锁过程总结

共享式获取与独占式获取的最主要区别在于同一时刻能否有多个线程同时获取到同步状态。通过调用acquireShared(int arg)方法可以共享式得获取同步状态。

同步器调用tryAcquireShared(int arg)方法尝试获取同步状态,其返回值为int类型,当返回值大于0时,表示能够获取同步状态。因此,在共享式获取的自旋过程中,成功获取同步状态并且退出自旋的条件就是tryAcquireShared(int arg)方法返回值大于等于0。共享式释放同步状态状态是通过调用releaseShared(int arg)方法

CountDownLatch、ReentrantReadWriteLock、Semaphore等都是共享式获取同步状态的。

wx.jpg

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 死磕Java并发:J.U.C之AQS简介

    Java的内置锁一直都是备受争议的,在JDK 1.6之前,synchronized这个重量级锁其性能一直都是较为低下,虽然在1.6后,进行大量的锁优化策略(死磕...

    程序猿DD
  • 【死磕Java并发】—–J.U.C之AQS:阻塞和唤醒线程

    此篇博客所有源码均来自JDK 1.8 在线程获取同步状态时如果获取失败,则加入CLH同步队列,通过通过自旋的方式不断获取同步状态,但是在自旋的过程中则需要判断当...

    用户1655470
  • 【死磕Java并发】—–J.U.C之AQS:同步状态的获取与释放

    此篇博客所有源码均来自JDK 1.8 在前面提到过,AQS是构建Java同步组件的基础,我们期待它能够成为实现大部分同步需求的基础。AQS的设计模式采用的模板方...

    用户1655470
  • Java并发编程(5)- J.U.C之AQS及其相关组件详解

    Java并发包(JUC)中提供了很多并发工具,这其中,很多我们耳熟能详的并发工具,譬如ReentrangLock、Semaphore,而它们的实现都用到了一个共...

    端碗吹水
  • 【死磕Java并发】----- 死磕 Java 并发精品合集

    【死磕 Java 并发】系列是 LZ 在 2017 年写的第一个死磕系列,一直没有做一个合集,这篇博客则是将整个系列做一个概览。

    用户1655470
  • 并发编程-15并发容器(J.U.C)核心 AbstractQueuedSynchronizer 抽象队列同步器AQS介绍

    并发编程-14线程安全策略之并发容器(J.U.C)中的集合类中介绍了J.U.C中的Collections集合 ,这篇博文我们将继续来看下J.U.C中的 AQS抽...

    小小工匠
  • 【死磕Java并发】—–J.U.C之并发工具类:Semaphore

    信号量Semaphore是一个控制访问多个共享资源的计数器,和CountDownLatch一样,其本质上是一个“共享锁”。

    用户1655470
  • 【死磕Java并发】—– J.U.C之并发工具类:Semaphore

    芋道源码
  • 【死磕Java并发】—–J.U.C之重入锁:ReentrantLock

    此篇博客所有源码均来自JDK 1.8 ReentrantLock,可重入锁,是一种递归无阻塞的同步机制。它可以等同于synchronized的使用,但是Reen...

    用户1655470
  • Java并发编程,深度探索J.U.C - AQS

    java.util.concurrent(J.U.C)大大提高了并发性能,AQS 被认为是 J.U.C 的核心。

    李红
  • Java并发编程,深度探索J.U.C - AQS

    java.util.concurrent(J.U.C)大大提高了并发性能,AQS 被认为是 J.U.C 的核心。

    李红
  • 聊聊面试中关于并发问题的应对方案

    技术zhai
  • 【死磕Java并发】—–J.U.C之读写锁:ReentrantReadWriteLock

    重入锁ReentrantLock是排他锁,排他锁在同一时刻仅有一个线程可以进行访问,但是在大多数场景下,大部分时间都是提供读服务,而写服务占有的时间较少。然而读...

    用户1655470
  • 【92期】面试官:你说你精通Java并发,那给我讲讲J.U.C吧

    来自:https://www.zybuluo.com/adamhand/note/1313016

    良月柒
  • 最强Java并发编程详解:知识点梳理,BAT面试题等

    在JUC锁: AbstractQueuedSynchonizer详解中类的内部类-conditionobject类有具体分析。

    Java团长
  • 慕课网高并发实战(七)- J.U.C之AQS

    3.不断重新尝试获取锁(当前结点为head的直接后继才会 尝试),如果获取失败,则会阻塞自己,直到被唤醒

    Meet相识
  • 【死磕Java并发】—–J.U.C之AQS:AQS简介

    Java的内置锁一直都是备受争议的,在JDK 1.6之前,synchronized这个重量级锁其性能一直都是较为低下,虽然在1.6后,进行大量的锁优化策略(【死...

    zhisheng
  • 【死磕Java并发】—–J.U.C之AQS:AQS简介

    Java的内置锁一直都是备受争议的,在JDK 1.6之前,synchronized这个重量级锁其性能一直都是较为低下,虽然在1.6后,进行大量的锁优化策略(【死...

    用户1655470
  • 死磕Java并发:J.U.C之Condition

    在没有Lock之前,我们使用synchronized来控制同步,配合Object的wait()、notify()系列方法可以实现等待/通知模式。在Java SE...

    程序猿DD

扫码关注云+社区

领取腾讯云代金券