深入解析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
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
AQS(AbstractQueuedSynchronizer)是Java中实现同步的框架,它提供了一种基于FIFO队列的阻塞和唤醒机制。AQS的阻塞队列原理是通过CLH(Craig, Landin, and Hagersten)队列来实现的。 CLH队列是一种虚拟的双向链表,它仅存在节点之间的关联关系,而不存在队列的实例。每个请求共享资源的线程都会被封装成一个CLH队列的节点(Node)。当线程请求共享资源时,它会被添加到CLH队列的尾部,并进入阻塞状态。 当共享资源被占用时,其他线程请求该资源的线程会被放入CLH队列的末尾,即排队等待。这种排队等待的方式可以保证请求资源的线程按照FIFO的顺序获得资源,避免了饥饿现象。当资源释放后,AQS会自动唤醒队列中的下一个线程,使其获得资源并继续执行。 需要注意的是,AQS同步队列(Sync queue)是一个双向链表,包括头节点(head)和尾节点(tail),用于后续的调度。而条件队列(Condition queue)是一个单向链表,只有在使用Condition时才会存在,并且可能会有多个条件队列。 总结一下,AQS实现阻塞队列原理是通过CLH队列来实现的,当共享资源被占用时,请求资源的线程会被添加到CLH队列中排队等待。当资源释放后,AQS会自动唤醒队列中的下一个线程,使其获得资源并继续执行。同步队列用于后续的调度,而条件队列只在使用Condition时才会存在。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

桃花猿

客官,赏点打酒钱

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

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

打赏作者

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

抵扣说明:

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

余额充值