线程安全(六)AQS 的工作原理

一、AQS 概述

1.1 什么是 AQS?

  • AQS 就是 AbstractQueuedSynchronizer 抽象类 的简称,它其实就是 JUC 包下的一个基类。
  • JUC 下的很多内容都是基于 AQS 实现了部分功能,比如:ReentrantLockThreadPoolExecutor阻塞队列CountDownLatchSemaphoreCyclicBarrier 等等都是基于 AQS 实现的。

1.2 AQS 与 synchronized 区别:

synchronized AQS
关键字,C++ 语言实现 Java 语言实现
悲观锁,自动释放锁 悲观锁,手动开启和关闭锁
锁竞争激烈,都是重量级锁,性能差 锁竞争激烈的情况下,提供了多种解决方案

1.3 AQS 常见的实现类:

  • ReentrantLock:阻塞式锁
  • Semaphore:信号量
  • CountDownLatch:计数器
  • CyclicBarrier:循环屏障

二、AQS 的工作原理

首先 AQS 中提供了一个由 volatile 修饰,并且采用 CAS 方式修改的 int 类型的 state 变量。

2.1 state 的用途:

  • ReentrantLock 中,使用 state 属性来标记当前互斥锁是否有线程持有,如果没有线程持有的话 state 就是 0,如果有线程持有的话 state 是大于 0 的。
  • ThreadPoolExecutor 中,worker 工作线程也是基于 state 变量来实现了一个锁的概念。
  • CountDownLatch 中,将 state 变量作为一个计数器,CountDownLatch 会在构建时声明好总数是多少。这个总数会直接赋值给 state,每次执行 countDown() 方法的时候,就会对 state 执行 -1 的操作。
  • Semaphore 中,也是基于 state 变量去记录现在有多少个资源,每个线程想要拿资源去操作时,也是对 state 进行 -1 的操作;当归还资源时,再执行 +1 操作。

由此可以看出,这个 state 变量是非常非常核心的一个属性。只要是用到了 AQS 基本上都用到了 state 属性。

2.2 AQS 双向链表:

除了 state 变量,AQS 中维护了一个 双向链表,有 head,有 tail,并且每个节点都是 Node 对象。

Node 源码如下所示:

static final class Node {
   
    // 表示线程以共享的模式等待锁
    static final Node SHARED = new Node();
    // 表示线程以独占的模式等待锁
    static final Node EXCLUSIVE = null;

    // 状态声明
    // 为0,表示当一个Node被初始化的时候的默认值
    // 为1,表示线程获取锁的请求已经取消了
    static final int CANCELLED =  1;
    // 为-1,表示线程已经准备好了,就等资源释放了
    static final int SIGNAL    = -1;
    // 为-2,表示节点在等待队列中,节点线程等待唤醒
    static final int CONDITION = -2;
    // 为-3,当前线程处在SHARED情况下,该字段才会使用(解决jdk1.5中的一个Bug)
    s
  • 15
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

不愿放下技术的小赵

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值