当前位置: 首页 > news >正文

Java并发之队列同步器AQS原理

一.什么是AQS?

  •  队列同步器(AbstractQueuedSychronizer)是用来构建锁或者其它同步组件的基础框架
  • 它使用了一个int成员变量state表示同步状态,通过内置的FIFO队列来完成资源获取线程的排队工作

AQS相当于一个state和一个队列组成

state:代表同步状态,他具体的值有代表加锁加锁和解锁的含义

二.AQS典型应用

  • 可重入锁(ReentrantLock)
  • 读写锁(ReentrantReadWriteLock)
  • CountDownLatch
  • Semephore

三.自定义一个Mutex独占锁

  • 独占锁相当于同一时间只有一个线程能去占用它,然后必须等到它释放锁之后,下一个线程才能去获取

AQS的实现采用的是模板模式,对外提供三类方法用于实现一个同步组件

第一类:使用3个方法访问或修改同步状态(state)

  • final int getState
  • final void setState
  • final boolean compareAndSetState  (使用CAS设置当前状态,能够保证状态设置的原子性)

CAS全称是Compare And Swap,是一种用于在多线程环境下实现同步功能的机制.CAS操作包括三个操作数:内存位置,预期数值和新值。CAS的实现逻辑是将内存位置处的数值与预期数值进行比较,若相等,则将内存位置处的值替换为新值,若不相等,则不做操作。

第二类:使用者继承AbstractQueuedSynchronizer并根据自己同步组件的一些特点来自定义实现的5个需要重写的方法(主要工作)

  • tryAcquire(int):独占方式。尝试获取资源,成功则返回true,失败则返回false。
  • tryRelease(int):独占方式。尝试释放资源,成功则返回true,失败则返回false
  • tryAcquireShared:共享方式。:尝试获取资源。负数表示失败;0表示成功,但没有剩余可用资源;正数表示成功,且有剩余资源
  • tryReleaseShared(int):共享方式。尝试释放资源,成功则返回true,失败则返回false.
  • isHeldExclusively():该线程是否正在独占资源。只有用到condition才需要去实现

第三类:9个模板方法,相当于把整个AQS流程串起来了

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

import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;class Mutex implements Lock {// 静态内部类,自定义同步器private static class Sync extends AbstractQueuedSynchronizer {// 是否处于占用状态protected boolean isHeldExclusively() {return getState() == 1;}// 当状态为0的时候获取锁public boolean tryAcquire(int acquires) {if (compareAndSetState(0, 1)) {setExclusiveOwnerThread(Thread.currentThread());return true;}return false;}// 释放锁,将状态设置为0protected boolean tryRelease(int releases) {if (getState() == 0) throw new IllegalMonitorStateException();setExclusiveOwnerThread(null);setState(0);return true;}// 返回一个Condition,每个condition都包含了一个condition队列Condition newCondition() { return new ConditionObject(); }}// 仅需要将操作代理到Sync上即可private final Sync sync = new Sync();@Overridepublic void lock() { sync.acquire(1); }@Overridepublic boolean tryLock() { return sync.tryAcquire(1); }@Overridepublic void unlock() { sync.release(1); }@Overridepublic Condition newCondition() { return sync.newCondition(); }@Overridepublic void lockInterruptibly() throws InterruptedException {sync.acquireInterruptibly(1);}@Overridepublic boolean tryLock(long timeout, java.util.concurrent.TimeUnit unit) throws InterruptedException {return sync.tryAcquireNanos(1, unit.toNanos(timeout));}
}

分析:

  1. 首先定义了一个静态内部类Sync,并重写了AbstractQueuedSynchronizer的部分方法
  2. 实现Lock接口:实现lock接口定义的六个方法,实现方式可以看到,基本就是直接代理到同步器sync上的模板方法(第三类)或重写过的方法(第二类)上来完成实现

总结:实现一个自定义锁的步骤:

  • 继承lock接口
  • 定义一个AQS的子类,作为锁的静态内部类。该类继承自AQS,也就拥有了AQS定义的九个模板方法。另外还需要实现AQS定义的五个可重写方法,重写实现的过程中需要用到3个同步状态的修改方法
  • 实现Lock规定的接口方法,原理就是将"操作"代理到AQS的子类sync上,即利用sync方法实现Lock

四.AQS实现原理分析

主要是为了维护一个state状态和一个队列

队列基本结构:同步器包含两个节点的引用(头尾节点)

队列节点:节点Node是构成同步对列的基础,它里面有一些状态(下述表格),获取同步状态失败的线程将会被包装成一个节点加入同步队列的尾部

新加入节点的过程:当有新结点需要加入的时候,需要保证线程安全,同步器提供了一个基于CAS的设置尾节点的方法:compareAndSetTail,他需要传递当前线程认为的尾节点和当前节点,只有设置成功后,当前节点才正式和之前的尾节点建立关联

首节点释放过程:同步队列遵循FIFO,首节点是获取同步状态成功的节点,首节点的线程在释放同步状态时,将会唤醒后续节点,而后续节点将会获取同步状态成功时将自己设置为首节点。


ReentrantLock的lock流程

五.AQS面试题

什么是AQS?

  • 队列同步器是用来构建锁或者其它同步组件的基础框架
  • 使用一个int成员变量表示同步状态,通过内置的FIFO队列实现线程的排队工作
  • 队列同步器的主要使用方式是继承,子类通过继承队列同步器并实现它的抽象方法来管理同步状态。
  • 在抽象方法实现的过程中免不了要对同步状态更改,这就需要使用3个方法getState,setState,compareAndSetState,

AQS 是怎么实现同步管理的?底层数据结构?

  • AQS主要依赖于一个双向链表和一个volatile类型的整数state来实现同步控制。该整数state用来表示同步状态,一般情况下state=0表示没有线程占用同步资源state>0表示有线程占用同步资源,state>1表示同步资源已经被争用了多次,比如ReentrantLock可以允许一个线程多次获得锁,每次state值加1。
  • AOS实现同步的关键在于,它提供了一个基于FIFO队列的同步队列,通过将等待线程加入同步队列中,然后在释放同步状态的时候,从同步队列中唤醒等待线程,从而实现了同步机制。
  • AQS的实现主要有两种方式:独占式(Exclusive)和共享式(Shared)。独占式是指只有一个线程可以占用同步资源,比如ReentrantLock,而共享式是指多个线程可以同时占用同步资源,比如CountDownLatch。在AOS中,这两种方式的实现是基本相同的,区别在于获取和释放同步状态的方式不同。
http://www.dtcms.com/a/503518.html

相关文章:

  • c++11可变模版参数 emplace接口 新的类功能 lambda 包装器
  • 手机代码网站有哪些问题吗制作视频特效
  • 济南正规的网站制作郑州做网站九零后网络
  • SQL入门:分页查询核心技术解析
  • 5.3 TCP (答案见原书 P252)
  • 教育房地产 网站建设中山网站建设找丁生
  • 【第十八周】自然语言处理的学习笔记03
  • 探索 Python 判断语句:逻辑与感性的交汇
  • 深圳哪家制作网站好成都近期发生的大事
  • IDEA Gradle并行编译内存溢出问题
  • 如何做电影网站赚钱瓯海住房与城乡建设局网站
  • 婚礼(一)
  • 电阻应变式传感器
  • 在开发过程中遇到问题如何解决,以及两个经典问题
  • 企业网站建设 属于什么费用个人博客网页设计
  • 网站怎么做301信息类网站 wordpress
  • MyBatis入门到精通(Mybatis学习笔记)
  • 一次渗透测试的全过程:从扫描到提权
  • 英语作文网站济南专业做公司网站的机构
  • 织梦后台做的网站怎么绑定域名做瞹视频网站
  • 网站悬浮代码做柱状图饼状图好看的网站
  • 2510d,C++与d互操作
  • 移动端漂亮网站今天出入济南最新通知
  • UV紫外相机的简单介绍和场景应用
  • 做公众号用什么网站吗404错误页面放在网站的哪里
  • uni-app 入门学习教程,从入门到精通, uni-app常用API的详细语法知识点(上)(5)
  • 设计模式篇之 访问者模式 Visitor
  • 疾控网站建设宗旨和目的wordpress设置为繁体字
  • 免费视频素材网站有哪些游戏制作公司
  • 09_Windows平台Redis开发环境配置完整指南