虽然synchronized提供了便捷性的隐式获取锁释放锁机制(基于JVM机制),但是它却缺少了获取锁与释放锁的可操作性,可中断、超时获取锁,且它为独占式在高并发场景下性能大打折扣。而ASQ,队列同步器是构建锁或者其他同步组件的基础框架(如ReentrantLock、ReentrantReadWriteLock、Semaphore等)

1.AQS简介

AQS的主要使用方式是继承,子类通过继承同步器并实现它的抽象方法来管理同步状态。

AQS解决了实现同步器时涉及当的大量细节问题,例如获取同步状态、FIFO同步队列。基于AQS来构建同步器可以带来很多好处。它不仅能够极大地减少实现工作,而且也不必处理在多个位置上发生的竞争问题。

在基于AQS构建的同步器中,只能在一个时刻发生阻塞,从而降低上下文切换的开销,提高了吞吐量。同时在设计AQS时充分考虑了可伸缩行,因此J.U.C中所有基于AQS构建的同步器均可以获得这个优势。

AQS使用一个int类型的成员变量state来表示同步状态,当state>0时表示已经获取了锁,当state = 0时表示释放了锁。它提供了三个方法(getState()、setState(int newState)、compareAndSetState(int expect,int update))来对同步状态state进行操作,当然AQS可以确保对state的操作是安全的。

AQS通过内置的FIFO同步队列来完成资源获取线程的排队工作,如果当前线程获取同步状态失败(锁)时,AQS则会将当前线程以及等待状态等信息构造成一个节点(Node)并将其加入同步队列,同时会阻塞当前线程,当同步状态释放时,则会把节点中的线程唤醒,使其再次尝试获取同步状态。

2.CLH同步队列

CLH同步队列是一个FIFO双向队列,AQS依赖它来完成同步状态的管理,当前线程如果获取同步状态失败时,AQS则会将当前线程已经等待状态等信息构造成一个节点(Node)并将其加入到CLH同步队列,同时会阻塞当前线程,当同步状态释放时,会把首节点唤醒(公平锁),使其再次尝试获取同步状态。

一个节点表示一个线程,它保存着线程的引用(thread)、状态(waitStatus)、前驱节点(prev)、后继节点(next)

3.同步状态获取与释放

AQS的设计模式采用的模板方法模式,子类通过继承的方式,实现它的抽象方法来管理同步状态,对于子类而言它并没有太多的活要做,AQS提供了大量的模板方法来实现同步,主要是分为三类:独占式获取和释放同步状态、共享式获取和释放同步状态、查询同步队列中的等待线程情况。自定义子类使用AQS提供的模板方法就可以实现自己的同步语义。

当前线程(Node)进入同步队列后,就会进入一个自旋的过程,每个节点都会自省地观察,当条件满足,获取到同步状态后,就可以从这个自旋过程中退出,否则会一直执行下去。

共享式与独占式的最主要区别在于同一时刻独占式只能有一个线程获取同步状态,而共享式在同一时刻可以有多个线程获取同步状态。例如读操作可以有多个线程同时进行,而写操作同一时刻只能有一个线程进行写操作,其他操作都会被阻塞。

4.阻塞和唤醒线程

在线程获取同步状态时如果获取失败,则加入CLH同步队列,通过通过自旋的方式不断获取同步状态,但是在自旋的过程中则需要判断当前线程是否需要阻塞。其方法是通过该线程的前驱结点判断当前节点是否需要被阻塞。如判断需要被阻塞,则再查看该线程的中断状态,如未被中断,则继续自旋,直到获取同步状态。如已被中断,则设置中断标志为true。

当线程释放同步状态后,则需要唤醒该线程的后继节点。

java asq_ASQ(AbstractQueuedSynchronizer)队列同步器相关推荐

  1. Java中的队列同步器AQS

    一.AQS概念 1.队列同步器是用来构建锁或者其他同步组件的基础框架,使用一个int型变量代表同步状态,通过内置的队列来完成线程的排队工作. 2.下面是JDK8文档中对于AQS的部分介绍 public ...

  2. JDK源码系列:AQS(队列同步器)原理

    大家好,好久不见,今天看下JDK中的JUC包中AQS(AbstractQueuedSynchronizer 队列同步器)的实现原理. JUCL下的锁和synchronized提供的锁的区别 1.锁的获 ...

  3. java同步队列_Java 中队列同步器 AQS(AbstractQueuedSynchronizer)实现原理

    前言 在 Java 中通过锁来控制多个线程对共享资源的访问,使用 Java 编程语言开发的朋友都知道,可以通过 synchronized 关键字来实现锁的功能,它可以隐式的获取锁,也就是说我们使用该关 ...

  4. Java中的锁---队列同步器

    2019独角兽企业重金招聘Python工程师标准>>> Lock接口 锁是用来控制多个线程访问共享资源的方式,一般来说,一个锁能够防止多个线程同时访问共享资源.Lock接口在使用时需 ...

  5. 【Java ASQ队列同步器实现原理】简单理解

    ASQ 1.概念 2.核心结构 3.实现原理 3.1 同步状态的获取 3.2 同步队列 3.3 独占式同步状态的获取 3.4 独占式同步状态的释放 1.概念 队列同步器AbstractQueuedSy ...

  6. java8 同步队列_秋招之路8:JAVA锁体系和AQS抽象队列同步器

    整个的体系图 悲观锁,乐观锁 是一个广义概念:体现的是看待线程同步的不同角度. 悲观锁 认为在自己使用数据的时候一定有别的线程来修改数据,在获取数据的时候会先加锁,确保数据不被别的线程修改. 实现:关 ...

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

    文章目录 J.U.C脑图 J.U.C核心AQS简介 AQS底层数据结构 AQS特点 J.U.C脑图 为了体现出AQS和线程池的重要性,上图单独将AQS和线程池拿出来了. J.U.C的构成如下: J.U ...

  8. 队列同步器 AbstractQueuedSynchronizer

    队列同步器  AbstractQueuedSynchronizer,是用来构建锁或者其他同步组件的基础框架,它使用了一个int成员变量,通过内置的FIFO队列来完成资源获取线程的排队工作. 同步器的主 ...

  9. Java并发编程之AbstractQueuedSychronizer(抽象队列同步器,简称AQS)

    AbstractQueuedSychronizer(抽象队列同步器,简称AQS): JDK的并发包(包名:java.util.concurrent,以下简称JUC)下面提供了很多并发操作的工具类,如: ...

最新文章

  1. LeetCode刷题记录2——217. Contains Duplicate(easy)
  2. python3 redis操作 错误 cannot import name 'StrictRedis' from 'redis'
  3. 【做题记录】[SCOI2009]围豆豆
  4. array关于map,reduce,filter的用法
  5. linux和GNU之间的关系
  6. linux搭建mysql主从模式_Linux下搭建MySQL的主从复制(一)
  7. 使用maven创建web项目
  8. 使用 leastsq 对指定函数格式进行最小二乘拟合
  9. golang gin mysql_Golang 的Gin框架入门教学
  10. finereport与finebi差别_FineBI与FineReport对比
  11. AUC、KS值、PSI值理解
  12. 推荐一个易学预测、学术研讨、资源分享网站:龙腾易学网
  13. chnsenticorp数据集及其处理
  14. 【ajax】7.请求:请求超时与网络异常处理+取消请求+请求重复发送问题
  15. 应用宝认领应用签名_腾讯开放平台第三方应用签名参数sig的说明
  16. 『Photo Shop实用技巧』之 去除红眼
  17. Word文件的只读模式没有密码怎么退出?
  18. Python实现投影法分割图像(一)
  19. OCO-2叶绿素荧光下载链接
  20. 零基础转行,你要不要去编程培训班?

热门文章

  1. (主从-阻抗)论文阅读笔记2
  2. 学习KEA之周期中断定时器PIT
  3. 如何做好流程管理?6条建议送给你!
  4. 直接在电脑上使用安卓系统
  5. java计算两个日期之间相差的天数的四种方法
  6. Slicer学习笔记(二十三)slicer调试自带模块
  7. 什么功夫最厉害?最厉害的武功一招能把人怎么样?
  8. 园区网核心交换机如何让同一VLAN不同的网段交互数据?
  9. W601温湿度监测与邮件报警系统 — 源码详解(邮件报警模块)
  10. PIC16F887的电子消毒柜设计