AQS原理及实战

AQS是一种提供了原子式管理同步状态、阻塞和唤醒线程功能以及CLH队列模型的简单框架。

Posted by guanyang on 2022-08-03
Words 598 and Reading Time 2 Minutes
Viewed Times

概要

  • Java中的大部分同步类(Lock、Semaphore、ReentrantLock等)都是基于AbstractQueuedSynchronizer(简称为AQS)实现的。
  • AQS是一种提供了原子式管理同步状态、阻塞和唤醒线程功能以及CLH队列模型的简单框架。
  • AQS同时提供了互斥模式(exclusive)和共享模式(shared)两种不同的同步逻辑。
  • 基于AQS同步器实现参考:
    • ReentrantLock
    • ReentrantReadWriteLock
    • Semaphore
    • CountDownLatch
    • ThreadPoolExecutor.Worker

核心思想

  • 共享资源(state)变量是volatile int类型,保证可见性
  • 基于CLH队列锁模型实现线程阻塞等待及唤醒机制,如图所示:

CLH队列

  • Sync queue: 同步队列是一个双向列表,包括head节点和tail节点

Sync queue

  • Condition queue: 非必须,单向列表,当程序中存在condition的时候才会存在此列表

Condition queue

设计思想

  • AQS使用一个int成员变量来表示同步状态
  • 使用Node实现FIFO队列,可以用于构建锁或者其他同步装置
  • AQS资源共享方式:独占Exclusive(排它锁模式)和共享Share(共享锁模式)

state状态

1
2
3
4
5
6
7
8
//表示该线程节点已释放(超时、中断),已取消的节点不会再阻塞
static final int CANCELLED = 1;
//表示该线程的后续线程需要阻塞,即只要前置节点释放锁,就会通知标识为 SIGNAL 状态的后续节点的线程
static final int SIGNAL = -1;
//表示该线程在condition队列中阻塞(Condition有使用)
static final int CONDITION = -2;
//表示该线程以及后续线程进行无条件传播(CountDownLatch中有使用)共享模式下
static final int PROPAGATE = -3;

自定义同步器实现

自定义同步器在实现时只需要实现共享资源state的获取与释放方式即可,主要实现以下几种方法:

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

If you like this blog or find it useful for you, you are welcome to comment on it. You are also welcome to share this blog, so that more people can participate in it. If the images used in the blog infringe your copyright, please contact the author to delete them. Thank you !

...

...

00:00
00:00