本文部分摘自《Java 并发编程的艺术》

概述

队列同步器 AbstractQueuedSynchronize(以下简称同步器),是用来构建锁(Lock)或者其他同步组件(JUC 并发包)的基础框架,它使用了一个 int 成员变量表示同步状态,通过内置的 FIFO 队列来完成资源获取线程的排队工作

同步器的主要使用方式是继承,子类通过继承同步器并实现它的抽象方法来管理同步状态,子类推荐被定义为自定义同步组件的静态内部类。同步器自身没有实现任何同步接口,它仅仅是定义了若干同步状态的获取和释放方法来供自定义组件使用

一言以蔽之,同步器是实现锁(也可以是任意同步组件)的一种方式,它屏蔽了更加底层的一些机制,使开发者更易于理解和使用

队列同步器的接口

同步器的设计是基于模板方法模式的,使用者需要继承队列同步器并重写指定的方法,随后将同步器组合在自定义同步组件的实现中,并调用同步器提供的模板方法,而这些模板方法将会调用使用者重写的方法

1. 访问或修改同步状态

重写同步器指定的方法时,需要使用同步器提供的如下三个方法来访问或修改同步状态:

getState()

获取当前同步状态

setState(int newState)

设置当前同步状态

compareAndSetState(int expect, int update)

使用 CAS 设置当前状态,该方法能保证状态设置的原子性

2. 同步器可重写的方法

方法名称

描述

protected boolean tryAcquire(int arg)

独占式获取同步状态,实现该方法需要查询当前状态,并判断同步状态是否符合预期,然后再进行 CAS 设置同步状态

protected boolean tryRelease(int arg)

独占式地释放同步状态,等待获取同步状态的线程将有机会获取同步状态

protected int tryAcquireShared(int arg)

共享式获取同步状态,返回大于等于 0 的值,表示获取成功,否则获取失败

protected boolean tryReleaseShared(int arg)

共享式释放同步状态

protected boolean isHeldExclusively()

当前同步器是否在独占模式下被线程占有,一般该方法表示是否被当前线程所独占

3. 同步器提供的模板方法

方法名称

描述

void acquire(int arg)

独占式获取同步状态,如果当前线程获取同步状态成功,则由该方法返回,否则,将会进入同步队列等待,该方法将会调用重写的 tryAcquire(int arg) 方法

void acquireInterruptibly(int arg)

与 acquire(int arg) 相同,但该方法响应中断,当前线程未获取到同步状态而进入同步队列中,如果当前线程被中断,则该方法会抛出 InterruptedException 并返回

boolean tryAcquireNanos(int arg, long nanos)

在 acquireInterruptibly(int arg) 的基础上增加了超时限制

void acquireShared(int arg)

共享式的获取同步状态,与独占式获取的主要区别是在同一时刻可以有多个线程获取到同步状态

void acquireSharedInterruptibly(int arg)

与 acquireShared(int arg) 相同,该方法响应中断

boolean tryAcquireSharedNanos(int arg, long nanos)

在 acquireSharedInterruptibly 的基础上增加了超时限制

boolean release(int arg)

独占式的释放同步状态,该方法会在释放同步状态之后,将同步队列中第一个节点包含的线程唤醒

boolean releaseShared(int arg)

共享式的释放同步状态

Collection getQueuedThreads()

获取等待在同步队列上的线程集合

4. 示例

下面通过一个独占锁的示例来深入了解一下同步器的工作原理。顾名思义,独占锁就是在同一时刻只能有一个线程获取到锁,其他获取锁的线程只能处于同步队列中等待,只有获取锁的线程释放了锁,后继的线程才能获取锁

public class Mutex implements Lock { /** * 自定义同步器 */ private static class Sync extends AbstractQueuedSynchronizer { @Override protected boolean isHeldExclusively() { // 是否处于占用状态 return getState() == 1; } @Override public boolean tryAcquire(int acquires) { // 当状态为 0 时获取锁 if (compareAndSetState(0, 1)) { setExclusiveOwnerThread(Thread.currentThread()); return true; } return false; } @Override protected boolean tryRelease(int releases) { // 释放锁,将状态设置为 0 if (getState() == 0) { throw new IllegalMonitorStateException(); } setExclusiveOwnerThread(null); setState(0); return true; } /** * 返回一个 Condition, 每个 condition 都包含一个 condition 队列 */ Condition newCondition() { return new ConditionObject(); } } private final Sync sync = new Sync(); @Override public void lock() { sync.acquire(1); } @Override public void lockInterruptibly() throws InterruptedException { sync.acquireInterruptibly(1); } @Override public boolean tryLock() { return sync.tryAcquire(1); } @Override public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { return sync.tryAcquireNanos(1, unit.toNanos(time)); } @Override public void unlock() { sync.release(1); } @Override public Condition newCondition() { return sync.newCondition(); }}

Mutex 中定义了一个静态内部类,该内部类继承了同步器并实现了独占式获取和释放同步状态。用户使用 Mutex 时并不会直接和内部同步器实现打交道,而是调用 Mutex 提供的方法,大大降低了实现一个可靠自定义组件的门槛

队列同步器的实现

1. 同步队列

同步器依赖内部的同步双向队列来完成同步状态的管理,当前线程获取同步状态失败后,同步器会将当前线程及其等待状态等信息构造成一个节点,并加入同步队列,同时阻塞当前线程。当同步状态释放后,会把首节点中的线程唤醒,使其再次尝试获取同步状态

节点是构成同步队列的基础,同步器拥有首节点(head)和尾结点(tail),没有成功获取同步状态的线程将会成为节点并加入该队列的尾部

同步队列的基本结构如下:

同步器将节点加入到同步队列的过程如图所示:

首节点是获取同步状态成功的节点,首节点线程在释放同步状态时,会唤醒后继节点,而后继节点将会在获取同步状态成功时将自己设置为首节点,过程如下:<.........>

java同步器有哪些_Java 队列同步器 AQS相关推荐

  1. java asq_ASQ(AbstractQueuedSynchronizer)队列同步器

    虽然synchronized提供了便捷性的隐式获取锁释放锁机制(基于JVM机制),但是它却缺少了获取锁与释放锁的可操作性,可中断.超时获取锁,且它为独占式在高并发场景下性能大打折扣.而ASQ,队列同步 ...

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

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

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

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

  4. Java中的队列同步器AQS

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

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

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

  6. 源码级深挖AQS队列同步器

    我们知道,在java中提供了两类锁的实现,一种是在jvm层级上实现的synchrinized隐式锁,另一类是jdk在代码层级实现的,juc包下的Lock显示锁,而提到Lock就不得不提一下它的核心队列 ...

  7. 【学习笔记】抽象队列同步器AQS应用之BlockingQueue详解

    文章目录 什么是AQS框架 Aqs核心源码 基于aqs实现的锁 BlockingQueue ArrayBlockingQueue LinkedBlockingQueue DelayQueue Bloc ...

  8. Java多线程(七)之同步器基础:AQS框架深入分析

    一.什么是同步器 多线程并发的执行,之间通过某种 共享 状态来同步,只有当状态满足 xxxx 条件,才能触发线程执行 xxxx . 这个共同的语义可以称之为同步器.可以认为以上所有的锁机制都可以基于同 ...

  9. AQS抽象队列同步器原理详解

    系列文章目录 第一节 synchronized关键字详解-偏向锁.轻量级锁.偏向锁.重量级锁.自旋.锁粗化.锁消除 AQS抽象队列同步器原理详解 系列文章目录 前言 一.AQS特性 二.AQS原理 1 ...

  10. 并发——抽象队列同步器AQS的实现原理

    一.前言 这段时间在研究Java并发相关的内容,一段时间下来算是小有收获了.ReentrantLock是Java并发中的重要部分,所以也是我的首要研究对象,在学习它的过程中,我发现它是基于抽象队列同步 ...

最新文章

  1. 2019年,自动化机器学习AutoML技术还火吗? | BDTC 2019
  2. 【Manning新书】Kafka实战
  3. BCH压力测试取得圆满成功,最大区块达21.3MB
  4. 最新3D GAN可生成三维几何数据了!模型速度提升7倍,英伟达斯坦福出品
  5. python各种包安装顺序_史上最全的Python包管理工具:Anaconda教程
  6. 解决跨域问题:No ‘Access-Control-Allow-Origin‘ header is present on the requested resource.
  7. 【python】yaml文件操作
  8. [转]神奇选股指标问世,每月稳定获利有保障
  9. Python实现对nginx日志access.log统计
  10. golang ide 环境搭建_新手引导 — Golang后端开发环境搭建
  11. Fiddler使用过程中无法抓取https的解决方法
  12. 汇编语言学习:VM上安装Win98系统
  13. 基于Pytorch实现人脸关键点检测模型MTCNN
  14. C#开发中三层架构BLL,DAL还有IBLL和IDAL接口,请问为什么要定义接口?有什么用啊?
  15. 计算机用户账户不见了,电脑用户账户找不到了怎么处理
  16. 引用第三方SDK产生依赖冲突
  17. Error response from daemon: conflict: unable to delete a9ac6b268134 (must be forced) - image is bein
  18. oracle季初,Oracle获取月初/月末/季初/季末/半年初/半年末/年初/年末
  19. return function和return function()的区别
  20. LaTeX 中文排版

热门文章

  1. Intel汇编与程序设计第五版3.4定义数据小节
  2. pycharm编程工具自带python环境_PyCharm配置Python3开发环境
  3. 判断DataTable为空,获取值,查询数据,datarow转datatable
  4. linux实验十shell程序设计,实验二Linux Shell编程.doc
  5. Win10 技巧:让任务栏时间显示 “秒”
  6. html 复选框全选、反选操作
  7. Yii2修改默认控制器
  8. iview render设置属性_iView 发布 3.4.0 版本,代号 BestLuck
  9. WORD的一个BUG
  10. 解决办法:Centos 7 SSH连接超时自动断开