AQS简简单单过一遍

只有光头才能变强!

本来我是打算在这章节中写Lock的子类实现的,但看到了AQS的这么一个概念,可以说Lock的子类实现都是基于AQS的

AQS我在面试题中也见过他的身影,但一直不知道是什么东西。所以本篇我就来讲讲AQS这个玩意吧,至少知道它的概念是什么,对吧~

那么接下来我们就开始吧~

一、AQS是什么?

首先我们来普及一下juc是什么:juc其实就是包的缩写(java.util.concurrnt)

不要被人家唬到了,以为juc是什么一个牛逼的东西。其实指的是包而已~

我们可以发现lock包下有三个抽象的类:

AQS简简单单过一遍

AbstractOwnableSynchronizer

AbstractQueuedLongSynchronizer

AbstractQueuedSynchronizer

通常地:AbstractQueuedSynchronizer简称为AQS

我们Lock之类的两个常见的锁都是基于它来实现的:

AQS简简单单过一遍

那么我们来看看AbstractQueuedSynchronizer到底是什么,看一个类是干什么的最快途径就是看它的顶部注释

AQS简简单单过一遍

通读了一遍,可以总结出以下比较关键的信息:

AQS其实就是一个可以给我们实现锁的框架

内部实现的关键是:先进先出的队列、state状态

定义了内部类ConditionObject

拥有两种线程模式

独占模式

共享模式

在LOCK包中的相关锁(常用的有ReentrantLock、 ReadWriteLock)都是基于AQS来构建

一般我们叫AQS为同步器

二、简单看看AQS

上面也提到了AQS里边最重要的是状态和队列,我们接下来就看看其源码是怎么样的...

2.1同步状态

使用volatile修饰实现线程可见性:

AQS简简单单过一遍

修改state状态值时使用CAS算法来实现:

AQS简简单单过一遍

2.2先进先出队列

这个队列被称为:CLH队列(三个名字组成),是一个双向队列

AQS简简单单过一遍

看看它队列源码的组成:

static final class Node { // 共享 static final Node SHARED = new Node(); // 独占 static final Node EXCLUSIVE = null; // 线程被取消了 static final int CANCELLED = 1; // 后继线程需要唤醒 static final int SIGNAL = -1; // 等待condition唤醒 static final int CONDITION = -2; // 共享式同步状态获取将会无条件地传播下去(没看懂) static final int PROPAGATE = -3; // 初始为0,状态是上面的几种 volatile int waitStatus; // 前置节点 volatile Node prev; // 后继节点 volatile Node next; volatile Thread thread; Node nextWaiter; final boolean isShared() { return nextWaiter == SHARED; } final Node predecessor() throws NullPointerException { Node p = prev; if (p == null) throw new NullPointerException(); else return p; } Node() { // Used to establish initial head or SHARED marker } Node(Thread thread, Node mode) { // Used by addWaiter this.nextWaiter = mode; this.thread = thread; } Node(Thread thread, int waitStatus) { // Used by Condition this.waitStatus = waitStatus; this.thread = thread; } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpgsjg.html