要点解说

AbstractQueuedSynchronizer简称AQS,它是java.util.concurrent包下CountDownLatch/FutureTask/ReentrantLock/RenntrantReadWriteLock/Semaphore实现的基础,所以深入理解AQS非常有必要。

AQS通过内部实现的FIFO等待队列来完成资源获取线程的等待工作,如果当前线程获取资源失败,AQS则会将当前线程以及等待状态等信息构造成一个Node结构的节点,并将其加入等待队列中,同时会阻塞当前线程;当其它获取到资源的线程释放持有的资源时,则会把等待队列节点中的线程唤醒,使其再次尝试获取对应资源。

源码解析

AbstractQueuedSynchronizer源码比较长,这里只分析主要的功能代码。首先,先看一下它内部定义的Node类的代码。

static final class Node {
//声明共享模式下的等待节点
static final Node SHARED = new Node();
//声明独占模式下的等待节点
static final Node EXCLUSIVE = null; //waitStatus的一常量值,表示线程已取消
static final int CANCELLED = 1;
//waitStatus的一常量值,表示后继线程需要取消挂起
static final int SIGNAL = -1;
//waitStatus的一常量值,表示线程正在等待条件
static final int CONDITION = -2;
//waitStatus的一常量值,表示下一个acquireShared应无条件传播
static final int PROPAGATE = -3; //waitStatus,其值只能为CANCELLED、SIGNAL、CONDITION、PROPAGATE或0
//初始值为0
volatile int waitStatus; //前驱节点
volatile Node prev; //后继节点
volatile Node next; //当前节点的线程,在节点初始化时赋值,使用后为null
volatile Thread thread; //下一个等待节点
Node nextWaiter; Node() {
} Node(Thread thread, Node mode) { // Used by addWaiter
this.nextWaiter = mode;
this.thread = thread;
} Node(Thread thread, int waitStatus) { // Used by Condition
this.waitStatus = waitStatus;
this.thread = thread;
}
}

上面的Node就是等待队列里的一个节点,具体结构如下:

接着,来看一下AbstractQueuedSynchronizer的三个重要属性:

	//等待队列的头结点
private transient volatile Node head;
//等待队列的尾节点
private transient volatile Node tail;
//同步状态,这个很重要
private volatile int state;

从这就可以得到同步队列的基本结构:

同时,同步器中提供了三个方法用于操作同步状态:

	protected final int getState() {
return state;
} protected final void setState(int newState) {
state = newState;
} //使用CAS设置同步状态,确保线程安全
protected final boolean compareAndSetState(int expect, int update) {
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}

AbstractQueuedSynchronizer类中其它方法主要是用于插入节点、释放节点,插入节点过程如下图所示:

释放头结点过程如下图所示:

分析小结

AbstractQueuedSynchronizer实现了对资源获取与释放的基础实现,真正使用到的地方还在是各个具体的功能类中,如CountDownLatch、ReentrantLock等,后面在这些类中会具体分析。

面试考点

AQS是什么?内部实现结构了解吗?

AbstractQueuedSynchronizer简称AQS,它为实现依赖于先进先出 (FIFO) 等待队列的阻塞锁和相关同步器(信号量等)提供一个基础实现框架。内部实现结构参考上面的图示作答。

高并发编程-AQS深入解析的更多相关文章

  1. 高并发编程-CountDownLatch深入解析

    要点解说 CountDownLatch允许一个或者多个线程一直等待,直到一组其它操作执行完成.在使用CountDownLatch时,需要指定一个整数值,此值是线程将要等待的操作数.当某个线程为了要执行 ...

  2. 多线程高并发编程(3) -- ReentrantLock源码分析AQS

    背景: AbstractQueuedSynchronizer(AQS) public abstract class AbstractQueuedSynchronizer extends Abstrac ...

  3. Java 面试知识点解析(二)——高并发编程篇

    前言: 在遨游了一番 Java Web 的世界之后,发现了自己的一些缺失,所以就着一篇深度好文:知名互联网公司校招 Java 开发岗面试知识点解析 ,来好好的对 Java 知识点进行复习和学习一番,大 ...

  4. 二十三、并发编程之深入解析Condition源码

    二十三.并发编程之深入解析Condition源码   一.Condition简介 1.Object的wait和notify/notifyAll方法与Condition区别 任何一个java对象都继承于 ...

  5. Java高并发编程基础三大利器之CountDownLatch

    引言 上一篇文章我们介绍了AQS的信号量Semaphore<Java高并发编程基础三大利器之Semaphore>,接下来应该轮到CountDownLatch了. 什么是CountDownL ...

  6. [ 高并发]Java高并发编程系列第二篇--线程同步

    高并发,听起来高大上的一个词汇,在身处于互联网潮的社会大趋势下,高并发赋予了更多的传奇色彩.首先,我们可以看到很多招聘中,会提到有高并发项目者优先.高并发,意味着,你的前雇主,有很大的业务层面的需求, ...

  7. java高并发编程(一)

    读马士兵java高并发编程,引用他的代码,做个记录. 一.分析下面程序输出: /** * 分析一下这个程序的输出 * @author mashibing */ package yxxy.c_005; ...

  8. java线程高并发编程

    java线程具体解释及高并发编程庖丁解牛 线程概述: 祖宗: 说起java高并发编程,就不得不提起一位老先生Doug Lea,这位老先生可不得了.看看百度百科对他的评价,一点也不为过: 假设IT的历史 ...

  9. Java 多线程高并发编程 笔记(一)

    本篇文章主要是总结Java多线程/高并发编程的知识点,由浅入深,仅作自己的学习笔记,部分侵删. 一 . 基础知识点 1. 进程于线程的概念 2.线程创建的两种方式 注:public void run( ...

随机推荐

  1. Linux CentOS7部署ASP.NET Core应用程序,并配置Nginx反向代理服务器

    前言: 本篇文章主要讲解的是如何在Linux CentOS7操作系统搭建.NET Core运行环境并发布ASP.NET Core应用程序,以及配置Nginx反向代理服务器.因为公司的项目一直都是托管在 ...

  2. 使用pyquery

    简单举例 from pyquery import PyQuery as pq html = ''' <div> <ul> <li class="item-O&q ...

  3. 第二十五章 system v消息队列(一)

    IPC对象的持续性 随进程持续 :一直存在直到打开的最后一个进程结束.(如pipe和FIFO) 随内核持续 :一直存在直到内核自举(内核自举就是把主引导记录加载到内存,并跳转执行这段内存)或显示删除( ...

  4. NOIP模拟 40

    考得更嘛也不是了. 不过如果不犯任何低错的话.. T1 我神奇地想要缩减码量 比如想把尽量多的$b[i]-1$省掉 于是求$b[i]$的时候先减了个一 本来是正的 减完就忘了他应该是非负的了 于是线段 ...

  5. MySQL 语句执行过程详解

    MySQL 原理篇 MySQL 索引机制 MySQL 体系结构及存储引擎 MySQL 语句执行过程详解 MySQL 执行计划详解 MySQL InnoDB 缓冲池 MySQL InnoDB 事务 My ...

  6. java-optional-快速使用-教程

    前言: 在公司中开发项目时碰到一个从Java8引入的一个Optional类,以前jdk版本使用的比较低,没有使用过,于是我在网上浏览了一些文档写篇文章学习总结一下,希望没有用过的朋友们都能够快速学习到 ...

  7. go中的关键字-select

    1. select的使用 定义:在golang里头select的功能与epoll(nginx)/poll/select的功能类似,都是坚挺IO操作,当IO操作发生的时候,触发相应的动作. 1.1 一些 ...

  8. 力扣(LeetCode)整数形式的整数加法 个人题解

    对于非负整数 X 而言,X 的数组形式是每位数字按从左到右的顺序形成的数组.例如,如果 X = 1231,那么其数组形式为 [1,2,3,1]. 给定非负整数 X 的数组形式 A,返回整数 X+K 的 ...

  9. 阿里云ECS服务器部署HADOOP集群(三):ZooKeeper 完全分布式集群搭建

    本篇将在阿里云ECS服务器部署HADOOP集群(一):Hadoop完全分布式集群环境搭建的基础上搭建,多添加了一个 datanode 节点 . 1 节点环境介绍: 1.1 环境介绍: 服务器:三台阿里 ...

  10. KDevelop

    ctags+vim还是太累了,还是使用IDE好,尤其是c++模板.KDevelop就不错,符号智能推导以及cmake项目管理和配置,还是挺好用的. Android端的ndk开发使用Android St ...