Java AQS 概述
AQS 概述
AQS(队列同步器,AbstractQueuedSynchronizer),是用来构建锁或其他同步组件的核心基础框架(比如 ReentrantLock、ReentrantReadWriteLock、Semaphore、CountDownLatch)
AQS的底层结构是:一个整型变量state表示同步状态,一个内置的FIFO队列(同步队列)来实现资源获取线程的同步等待排队,若干个FIFO队列(条件等待队列)来完成持有资源线程的条件等待排队。同步队列如下:
AQS的使用方式
同步器的设计是基于模板方法模式的,其使用方式是继承,子类通过继承同步器并重写指定的模板方法,模板方法分为3类:独占式获取与释放同步状态、共享式获取与释放同步状态、查询队列中的等待线程。在重写过程中可以使用同步器提供的3个方法来管理同步状态state:getState()、setState()和compareAndSetState(),因为它们能够保证state的改变是并发安全的。
当实现一个自定义同步组件时,推荐在内部聚合/组合一个同步器的实现类,该自定义同步组件将通过调用同步器提供的模板方法来实现自己的同步语义。为什么不直接使用同步器呢?因为同步器自身没有实现任何同步接口,它仅仅是定义了若干管理同步状态的方法,这样有利于实现各种类型的同步组件
同步器与锁的关系
同步器是实现锁的关键,在锁的实现中聚合/组合了一个同步器,利用该同步器实现了锁的语义。
可以这样理解二者之间的关系:锁是面向使用者的,它定义了使用者与锁的交互接口,隐藏了实现细节;而同步器面向的是锁的实现者,它简化了锁的实现方式,包括屏蔽同步状态管理、线程的排队、等待与唤醒等底层操作。锁和同步器很好地隔离了使用者和实现者所需关注的领域。
AQS:获取与释放同步状态
1.独占式获取同步状态
查看源码 AbstractQueuedSynchronizer.acquire(..)
public final void acquire(int arg) {
//tryAcquire(..) 尝试获取同步状态,由子类重写,最经典的实现是互斥锁:state=0(锁自由),state>0(锁被占用)
//acquireQueued(..) 进入同步队列,阻塞等待获取锁
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
由于acquire(..)方法不响应中断,因此AQS也提供了响应中断、超时等待的方法:acquireInterruptibly(..)、tryAcquireNanos(..)
2.独占式释放同步状态
查看源码 AbstractQueuedSynchronizer.release(..)
public final boolean release(int arg) {
//tryAcquire(..) 尝试释放同步状态,由子类重写
if (tryRelease(arg)) {
Node h = head;
//unparkSuccessor(..) 唤醒被挂起的Node(线程)
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
3.共享式获取同步状态
查看源码 AbstractQueuedSynchronizer.acquireShared(..)
public final void acquireShared(int arg) {
//tryAcquireShared(..) 尝试获取同步状态,由子类重写,最经典的实现是信号量:state>0(锁很多),state<0(锁不足)
//doAcquireShared(..) 进入同步队列,阻塞等待获取锁
if (tryAcquireShared(arg) < 0)
doAcquireShared(arg);
}
由于acquireShared(..)方法不响应中断,因此AQS也提供了响应中断、超时等待的方法:acquireSharedInterruptibly(..)、tryAcquireSharedNanos(..)
4.共享式释放同步状态
查看源码 AbstractQueuedSynchronizer.
public final boolean releaseShared(int arg) {
//tryReleaseShared(..) 尝试释放同步状态,由子类重写
if (tryReleaseShared(arg)) {
//doReleaseShared(..) 唤醒被挂起的Node(线程)
doReleaseShared();
return true;
}
return false;
}
参考文章:
Java AQS 概述的更多相关文章
- Java AQS学习
参考原文: Java并发之AQS详解 <Java并发编程的艺术> AQS 概述 AQS简介 AQS(AbstractQueuedSynchronizer)就是一个抽象的队列同步器,它是用来 ...
- Java Annotation概述
@(Java)[Annotation|Java] Java Annotation概述 用途 编译器的相关信息,如用于检测错误和一些警告 编译时和部署时的处理,如一些软件用于自动生成代码之类的 运行时处 ...
- 《java集合概述》
JAVA集合概述: Collection: |---List有序的:通过索引就可以精确的操作集合中的元素.元素是可以重复的. List提供了增删改查的动作. 增加add(element) add(in ...
- Java的概述以及语法
Java的语法分为标示符和数据类型 Java的概述: 一些手打的: long l = 12345; //隐式转换 int a = (int)121234567L; //强制转换 float f =12 ...
- Java集合概述、Set集合(HashSet类、LinkedHashSet类、TreeSet类、EnumSet类)
Java集合概述.Set集合(HashSet类.LinkedHashSet类.TreeSet类.EnumSet类) 1.Java集合概述1)数组可以保存多个对象,但数组长度不可变,一旦在初始化数组时指 ...
- Java笔记:Java集合概述和Set集合
本文主要是Java集合的概述和Set集合 1.Java集合概述 1)数组可以保存多个对象,但数组长度不可变,一旦在初始化数组时指定了数组长度,这个数组长度就是不可变的,如果需要保存数量变化的数据,数组 ...
- Java NIO学习笔记一 Java NIO概述
Java NIO概述 Java NIO(新的IO)是Java的替代IO API(来自Java 1.4),这意味着替代标准的 java IO和java Networking API.Java NIO提供 ...
- java基础---java语言概述
一.计算机编程的两种范型 1.面向过程的模型---具有线性执行特点,认为是代码作用于数据. 2.面向对象的模型---围绕它的数据(即对象)和为这个数据定义的接口来组织程序:实际上是用数据控制代码的访问 ...
- Java核心技术(Java白皮书)卷Ⅰ 第一章 Java程序设计概述
第1章 Java程序设计概述1.1 Java程序设计平台 具有令人赏心悦目的语法和易于理解的语言,与其他许多优秀语言一样,Java满足这些要求. 可移植性 垃圾收集 提供大型的库 如果想要有奇特的绘 ...
随机推荐
- 基础select语句详解
在数据库操作语句中,使用最频繁,也被认为最重要的是 SELECT 查询语句.我们已经在不少地方用到了 SELECT * FROM table_name; 这条语句用于查看一张表中的所有内容. 而 SE ...
- centos7zabbix-agen安装
安装包下载地址:http://www.zabbix.com/download.php 下载对应rpm包 http://repo.zabbix.com/zabbix/ wget http://r ...
- LeetCode编程训练 - 回溯(Backtracking)
回溯基础 先看一个使用回溯方法求集合子集的例子(78. Subsets),以下代码基本说明了回溯使用的基本框架: //78. Subsets class Solution { private: voi ...
- CAS实现单点登录SSO执行原理及部署
一.不落俗套的开始 1.背景介绍 单点登录:Single Sign On,简称SSO,SSO使得在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统. CAS框架:CAS(Centra ...
- [Swift]LeetCode1022. 从根到叶的二进制数之和 | Sum of Root To Leaf Binary Numbers
Given a binary tree, each node has value 0 or 1. Each root-to-leaf path represents a binary number ...
- 修复FFMPEG 复用 PAT、PMT发送间隔小于25ms的错误
目录 分析ffmpeg源码 分析问题 修改源码解决问题 分析ffmpeg源码 分析问题 mpegtsenc.c 找到发送PAT.PMT的函数 /* send SDT, PAT and PMT tabl ...
- 一张图看懂STM32芯片型号的命名规则
意法半导体已经推出STM32基本型系列.增强型系列.USB基本型系列.增强型系列:新系列产品沿用增强型系列的72MHz处理频率.内存包括64KB到256KB闪存和 20KB到64KB嵌入式SRAM.新 ...
- redux-thunk 源码学习记录
redux触发store更新,使用的dispatch(action),在关于createStore的源码解读中可以看到,store.dispatch限制了action必须是一个纯对象.是为了保持red ...
- iOS学习—— UISearchBar的使用
转载自:http://blog.sina.com.cn/s/blog_7b9d64af0101dfg8.html 最近用到搜索功能.于是,经过不断的研究,终于,有点懂了. 那就来总结一下吧,好记性不如 ...
- github pages绑定域名
网上很多人问 github 绑定域名要不要备案,很多人的回答是: 国内主机需要备案,国外主机不用 这个说法是没错的,但是却没有直接回答出 github pages 是否需要备案! 首先声明 githu ...