博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
AQS
阅读量:5088 次
发布时间:2019-06-13

本文共 1025 字,大约阅读时间需要 3 分钟。

AQS

概述
  • AQS,即AbstractQueuedSynchronizer, 队列同步器,它是Java并发用来构建锁和其他同步组件的基础框架
AQS原理
  • AQS的实现依赖内部的同步队列(FIFO双向队列),如果当前线程获取同步状态失败,AQS会将该线程以及等待状态等信息构造成一个Node,将其加入同步队列的尾部,同时阻塞当前线程,当同步状态释放时,唤醒队列的头节点。
  • AQS最主要的三个成员变量:
private transient volatile Node head;        private transient volatile Node tail;    private volatile int state;
  • 上面提到的同步状态就是这个int型的变量state. head和tail分别是同步队列的头结点和尾结点。假设state=0表示同步状态可用(如果用于锁,则表示锁可用),state=1表示同步状态已被占用(锁被占用)。
AQS获取和释放同步状态的过程
  • 获取同步状态
    • 假设线程A要获取同步状态(这里想象成锁,方便理解),初始状态下state=0,所以线程A可以顺利获取锁,A获取锁后将state置为1。在A没有释放锁期间,线程B也来获取锁,此时因为state=1,表示锁被占用,所以将B的线程信息和等待状态等信息构成出一个Node节点对象,放入同步队列,head和tail分别指向队列的头部和尾部(此时队列中有一个空的Node节点作为头点,head指向这个空节点,空Node的后继节点是B对应的Node节点,tail指向它),同时阻塞线程B(这里的阻塞使用的是LockSupport.park()方法)。后续如果再有线程要获取锁,都会加入队列尾部并阻塞。
  • 释放同步状态
    • 当线程A释放锁时,即将state置为0,此时A会唤醒头节点的后继节点(所谓唤醒,其实是调用LockSupport.unpark(B)方法),即B线程从LockSupport.park()方法返回,此时B发现state已经为0,所以B线程可以顺利获取锁,B获取锁后B的Node节点随之出队。
使用场景
  • ReentrantLock,CountdowLatch就是基于AQS实现的,用法是通过继承AQS实现其模版方法,然后将子类作为同步组件的内部类
参考

转载于:https://www.cnblogs.com/frankltf/p/10345372.html

你可能感兴趣的文章
前端性能优化之数据存取(二)
查看>>
[bzoj4889] [Tjoi2017]不勤劳的图书管理员
查看>>
Effective Objective-C 2.0
查看>>
php异常处理示例
查看>>
JS小问题之——如何用原生js触发事件
查看>>
按值传递
查看>>
将 Excel 2007 读取到 Byte[], 然后再保存到新的Excel文件中, 这时打开新文件会出错....
查看>>
react学习笔记2--练习Demos
查看>>
图像预处理第9步:存为.bmp文件
查看>>
使用STL map和模板时遇到的一个错误
查看>>
Linux查看CPU《型号..》《内存..》《硬盘..》《系统..》
查看>>
github使用个人总结
查看>>
异常处理
查看>>
Django(四) ORM 外键操作及初识Ajax
查看>>
局部最优解与全局最优解(转)
查看>>
EM算法与混合高斯模型
查看>>
Leetcode 86.分隔链表
查看>>
学习前端开发的第三周
查看>>
bzoj4390: [Usaco2015 dec]Max Flow
查看>>
安装前端脚手架
查看>>