概述

全称是 AbstractQueuedSynchronizer,是阻塞式锁和相关的同步器工具的框架

核心方法

tryAcquire()
tryRelease()
tryAcquireShared()
tryReleaseShared()
isHeldExclusively()

特点

  • 用 state 属性来表示资源的状态(分独占模式和共享模式),子类需要定义如何维护这个状态,控制如何获取锁和释放锁
getState - 获取 state 状态
setState - 设置 state 状态
compareAndSetState - cas 机制设置 state 状态
独占模式是只有一个线程能够访问资源,而共享模式可以允许多个线程访问资源

独占锁

公平锁:按照线程在队列中的排队顺序,先到者先拿到锁
非公平锁:当线程要获取锁时,无视队列顺序直接去抢锁,谁抢到就是谁的
  • 独占锁实现
ReentrantLock、ReentrantReadWriteLock.WriteLock
  • 独占锁实现需要重写的方法
protected boolean tryAcquire(int arg)
//返回值表示释放锁是否成功
protected boolean tryRelease(int arg)

共享锁

ReentrantReadWriteLock.ReadLock、CountDownLatch、
CyclicBarrier、Semaphore
  • 共享锁实现需要重写的方法
//返回值表示获得锁后还剩余的许可数量
protected int tryAcquireShared(int arg)
//返回值表示释放锁是否成功
protected boolean tryReleaseShared(int arg)

设计思想

  • 获取锁的逻辑
while(state 状态不允许获取《未获得锁》) {if(队列中还没有此线程) {入队并阻塞}
}
《获得锁》
当前线程出队
  • 释放锁的逻辑
if(state 状态允许了) {恢复阻塞的线程(s)
}

要点

原子维护 state 状态
阻塞及恢复线程
维护队列
  • state 设计
state 使用 volatile 配合 cas 保证其修改时的原子性
state 使用了 32bit int 来维护同步状态,因为当时使用 long 在很多平台下测试
的结果并不理想
  • 阻塞恢复设计
  • 队列设计

自定义锁(不可重入锁)

思想: 使用Lock接口,底层实现使用自定义同步器
class MyLock implements Lock {// 独占锁  同步器类class MySync extends AbstractQueuedSynchronizer {@Overrideprotected boolean tryAcquire(int arg) {if (compareAndSetState(0, 1)) {// 加上了锁,并设置 owner 为当前线程setExclusiveOwnerThread(Thread.currentThread());return true;}return false;}@Overrideprotected boolean tryRelease(int arg) {setExclusiveOwnerThread(null);setState(0);return true;}@Override // 是否持有独占锁protected boolean isHeldExclusively() {return getState() == 1;}public Condition newCondition() {return new ConditionObject();}}private MySync sync = new MySync();@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();}
}
@Slf4j(topic = "c.TestAqs")
public class TestAqs {public static void main(String[] args) {MyLock lock = new MyLock();new Thread(() -> {lock.lock();try {log.debug("locking...");sleep(1);} finally {log.debug("unlocking...");lock.unlock();}}, "t1").start();new Thread(() -> {lock.lock();try {log.debug("locking...");} finally {log.debug("unlocking...");lock.unlock();}}, "t2").start();}
}
17:38:08.443 c.TestAqs [t1] - locking...
17:38:09.450 c.TestAqs [t1] - unlocking...
17:38:09.450 c.TestAqs [t2] - locking...
17:38:09.450 c.TestAqs [t2] - unlocking...

AQS explanation相关推荐

  1. 05.抽象队列同步器AQS应用之Lock详解

    AQS应用之Lock Java并发编程核心在于java.concurrent.util包而juc当中的大多数同步器实现都是围绕着共同的基础行为,比如等待队列.条件队列.独占获取.共享获取等,而这个行为 ...

  2. java aqs源码_Java-AQS源码详解(细节很多!)

    ReentrantLock调用lock()时时序图: addWaiter方法: enq方法:自旋 它维护了一个volatile int state(代表共享资源)和一个FIFO线程等待队列(多线程争用 ...

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

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

  4. Java中的锁原理、锁优化、CAS、AQS详解

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:景小财 www.jianshu.com/p/e674ee68 ...

  5. JUC AQS ReentrantLock源码分析

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

  6. java多线程aqs实现工具类_Java并发多线程 - 并发工具类JUC

    (adsbygoogle = window.adsbygoogle || []).push({}); 安全共享对象策略 1.线程限制 : 一个被线程限制的对象,由线程独占,并且只能被占有它的线程修改 ...

  7. Java并发同步器AQS

    AQS是AbstractQueuedSynchronizer的简写,中文名应该叫抽象队列同步器(我给的名字,哈哈),出生于Java 1.5. 一.什么是同步器 多线程并发的执行,之间通过某种 共享 状 ...

  8. JAVA那点破事!并发、IO模型、集合、线程池、死锁、非阻塞、AQS....

    关于Java面试,面试官一般喜欢问哪些问题? 本文对一些高频问题做了汇总,为了便于大家查找问题,了解全貌,整理个目录,我们可以快速全局了解关于 JAVA 接下来,我们逐条来看看每个问题及答案 JDK. ...

  9. 扔掉源码,15张图带你彻底理解java AQS

    java中AQS是AbstractQueuedSynchronizer类,AQS依赖FIFO队列来提供一个框架,这个框架用于实现锁以及锁相关的同步器,比如信号量.事件等. 在AQS中,主要有两部分功能 ...

最新文章

  1. 提示-bash: telnet: command not found的解决方法
  2. Android本地视频播放器开发--视频解码
  3. 《C++ Primer》7.5.1节练习
  4. STL::map默认会按照.first的字母顺序排列
  5. linux ps 详解 博客,Linux PS 命令 详解(转)
  6. Unity3d 札记-Let's try shooting 知识点汇总
  7. 计算机课计划,计算机教学计划汇总
  8. 退休的姐妹们,你们还打工吗?
  9. 内存之私有sql区和共享sql区
  10. bzoj1045题解
  11. 高通平台开发系列讲解(音频篇)Codec驱动移植步骤
  12. k线顶分型 python_顶分型K线形态形态特征及操作要领
  13. 阿里云服务器被攻击了怎么办?
  14. CSS属性分类扫描-表格属性
  15. Java学习笔记分享之MyBatis篇(中)
  16. 四川省国际科技合作基地(国合基地)申报条件程序
  17. 改良的用于情感分类的餐馆评论数据集
  18. vim之快速查找功能
  19. SyntaxError: Missing parentheses in call to ‘print‘. 正解
  20. 咸鱼Micropython—LED用法

热门文章

  1. php爬取百度相关关键词,PHP实现抓取百度搜索结果页面【相关搜索词】并存储到txt文件示例...
  2. 深入解读MIMO原理及测试方法
  3. 【ARXIV2202】Visual Attention Network
  4. C语言学习之路——COORD
  5. 常用的安全算法-数字摘要、对称加密、非对称加密详解
  6. 【微信公众号开发】六、微信JS的使用
  7. 墨刀导出只有一个html文件,墨刀免费版,一个项目最多可以创建几个页面
  8. java guava table_java – 使用Guava的Tables.toTable
  9. 极路由2-极贰9007的降级root攻略
  10. 易语言自定义窗口过程