并发容器J.U.C -- AQS组件(一)

AQS简介

AQS全名:AbstractQueuedSynchronizer,是并发容器J.U.C(java.lang.concurrent)下locks包内的一个类。它实现了一个FIFO(FirstIn、FisrtOut先进先出)的队列。底层实现的数据结构是一个双向列表
AQS数据结构
Sync queue:同步队列,是一个双向列表。包括head节点和tail节点。head节点主要用作后续的调度。
Condition queue:非必须,单向列表。当程序中存在cindition的时候才会存在此列表。

AQS设计原理

  1. 使用Node实现FIFO队列,可以用于构建或者其他同步装置的基础框架。
  2. 利用int类型标识状态。在AQS类中有一个叫做state的成员变量(private volatile int state;),表示获取锁的线程数(state=0,表示还没有线程获取锁,1表示有线程获取了锁。大于1表示重入锁的数量)和一个同步组件ReentrantLock。
  3. 使用方法是继承,基于模板方法。
  4. 子类通过继承并通过实现它的方法管理其状态(acquire和release方法操纵状态)。
  5. 可实现排它锁和共享锁模式(独占、共享)。AQS的功能主要分为两类:独占和共享。子类,要么实现并使用了它的独占功能的api,要么使用了共享锁的功能,而不会同时使用两套api,即便是最有名的子类ReentrantReadWriteLock也是通过两个内部类读锁和写锁分别实现了两套api来实现的。

可重入锁,指对同一个ReentrantLock对象多次执行lock()加锁和unlock()释放锁。

AQS实现思路

  1. AQS内部维护了一个CLH队列来管理锁。
  2. 线程会首先尝试获取锁,如果失败就将当前线程及等待状态等信息包装成一个node节点加入到同步队列sync queue里。
  3. 不断的重新尝试获取锁(当前节点为head的直接后继才会尝试)。如果失败就会阻塞自己,直到自己被唤醒。
  4. 当持有锁的线程释放锁的时候,会唤醒队列中的后继线程。
    在这里插入图片描述

释放锁

唤醒,获取锁
图片参考:大白话聊聊Java并发面试问题之谈谈你对AQS的理解?【石杉的架构笔记】

猜你喜欢

转载自blog.csdn.net/eluanshi12/article/details/85258162