深入解析AQS队列同步器的底层原理

一、AQS

1.1 概述

全称为(AbstractQueuedSynchronizer, AQS) ,队列同步器

  1. 用来构建锁或其他同步组件的基础框架,使用了一个java volatile int state成员变量表示同步状态(代表共享资源),通过内置的FIFO双向队列来完成资源获取线程的排队工作;
  2. 定义为volatile能够保证多线程下的可见性,当state = 1时代表当前对象锁已经被占有,其他线程加锁会失败。加锁失败的线程会被放入一个FIFO队列中.

1.2 主要使用方式

因采用模板方法模式继承,子类通过继承同步器并实现它的抽象方法来管理同步器

1.3 主要方法

1. getState():获取当前同步状态
2. setState(int newState):设置当前同步状态
3. compareAndSetState(int expect、update):使用CAS来设置当前状态,保证状态设置的原子性;
4. 独占模式是只有一个线程能够访问资源,而共享模式可以允许多个线程访问资源
状态的改变主要通过这三个方法来进行,而且state的操作都是通过CAS来保证其并发修改的安全性。

二、底层原理

底层是一个FIFO双向队列,队列上是一个个节点Node,Node是内部类,封装了一些信息,主要有:

static final class Node { 
  /*
    * 1. signal = -1, 后继节点的线程处于等待状态。如果当前线程释放了同步状态,
    * 将会通知后继节点,使后继节点的线程得以运行 
    * 2. condition = -2, 节点在【等待队列】中,节点线程等待在Condition上,当其它
    * 线程对Condition调用了signal()方法后,该节点将会从等待队列中转移到同步队列,
    * 加入对同步状态的获取中
    */  
     volatile int waitStatus;
     volatile Node prev; 
     volatile Node next; 
     volatile Thread thread; // 获取同步状态的线程
     Node nextWaiter; // 等待队列中的后继节点
}

2.1 独占式同步状态获取和释放

获取逻辑: 主要是java acquire来完成,该方法定义了一个抽象模板,内部的java tryAcquire方法由子类来实现,java acquireQueued(addWaiter)是默认实现方法。
在这里插入图片描述
释放逻辑: 主要由java release方法来实现,该方法也是模板模式,````java tryRelease方式需要由子类自己实现, java unparkSuccessor```唤醒方法由默认实现。具体流程如下:
在这里插入图片描述

2.2 共享式同步状态获取和释放

与独占式的区别在于,同一时刻一个资源能否被多个线程访问。AQS也提供了共享式同步状态获取和释放的模板模式方法,分别为acquireShared和releaseShared。
加锁流程: 和独占式类似,不过提供的由子类实现的tryAcquireShared方法,返回值为int,当返回值 >= 0的时候,可以认为获取锁成功,否则,进入同步队列;
解锁流程: 和独占式类似,需要子类实现tryReleaseShared方法,来保证锁的释放。

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

桃花猿

客官,赏点打酒钱

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值