AQS源码探究_02 AQS简介及属性分析

简介: 1. 简介

AQS的全称是AbstractQueuedSynchronizer,它的定位是为Java中几乎所有的锁和同步器提供一个基础框架。


AQS是基于FIFO的队列实现的,并且内部维护了一个状态变量state,通过原子更新这个状态变量state即可以实现加锁解锁操作。


2. 主要内部类Node

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;
    // 标识线程等待在一个条件上
    static final int CONDITION = -2;
    // 标识后面的共享锁需要无条件的传播(共享锁需要连续唤醒读的线程)
    static final int PROPAGATE = -3;
    // 当前节点保存的线程对应的等待状态(node状态可选值:0,SIGNAL,CANCELLED,CONDITION,PROPAGATE)
    // waitStatus == 0 默认状态
    // waitStatus > 0 取消状态
    // waitStatus == -1 表示当前node如果是head节点时,释放锁之后需要唤醒它的后继节点
    volatile int waitStatus;
    // 前一个节点(前驱):用于node构建 FIFO队列~
    volatile Node prev;
    // 后一个节点(后驱):用于node构建 FIFO队列~
    volatile Node next;
    // 当前node节点封装的线程
    volatile Thread thread;
    // 下一个等待在条件上的节点(Condition锁时使用)
    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
        // 把共享模式还是互斥模式存储到nextWaiter这个字段里面了
        this.nextWaiter = mode;
        this.thread = thread;
    }
    // 节点的构造方法
    Node(Thread thread, int waitStatus) { // Used by Condition
        // 等待的状态,在Condition中使用
        this.waitStatus = waitStatus;
        this.thread = thread;
    }
}

双链表结构,节点中保存着当前线程、前一个节点、后一个节点以及线程的状态等信息。

3. 主要属性

// 队列的头节点: 任何时刻,头结点对应的线程就是当前持锁线程~
private transient volatile Node head;
// 队列的尾节点:(阻塞队列不包含头结点head,是从head.next 开始,到 tail 结束,这个区间是阻塞队列~)
private transient volatile Node tail;
// 控制加锁解锁的状态变量
// 独占模式下:0 表示未加锁状态, >0 表示已加锁状态
private volatile int state;

定义了一个状态变量和一个队列,状态变量用来控制加锁解锁,队列用来放置等待的线程。

注意:这几个变量都要使用volatile关键字来修饰,因为是在多线程环境下操作,要保证它们的值修改之后对其它线程立即可见。

这几个变量的修改是直接使用的Unsafe这个类来操作的:

// 获取Unsafe类的实例,注意这种方式仅限于jdk自己使用,普通用户是无法这样调用的
private static final Unsafe unsafe = Unsafe.getUnsafe();
// 状态变量state的偏移量
private static final long stateOffset;
// 头节点的偏移量
private static final long headOffset;
// 尾节点的偏移量
private static final long tailOffset;
// 等待状态的偏移量(Node的属性)
private static final long waitStatusOffset;
// 下一个节点的偏移量(Node的属性)
private static final long nextOffset;
static {
    try {
        // 获取state的偏移量
        stateOffset = unsafe.objectFieldOffset
            (AbstractQueuedSynchronizer.class.getDeclaredField("state"));
        // 获取head的偏移量
        headOffset = unsafe.objectFieldOffset
            (AbstractQueuedSynchronizer.class.getDeclaredField("head"));
        // 获取tail的偏移量
        tailOffset = unsafe.objectFieldOffset
            (AbstractQueuedSynchronizer.class.getDeclaredField("tail"));
        // 获取waitStatus的偏移量
        waitStatusOffset = unsafe.objectFieldOffset
            (Node.class.getDeclaredField("waitStatus"));
        // 获取next的偏移量
        nextOffset = unsafe.objectFieldOffset
            (Node.class.getDeclaredField("next"));
    } catch (Exception ex) { throw new Error(ex); }
}
// 调用Unsafe的方法原子更新state
protected final boolean compareAndSetState(int expect, int update) {
    return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}

4. 父类属性

AQS还用到了其父类AbstractOwnableSynchronizer的一些属性:

// 独占模式下:表示当前持有锁的线程~
private transient Thread exclusiveOwnerThread;


相关文章
|
5月前
|
Java 调度
Java并发基础-线程简介(状态、常用方法)
Java并发基础-线程简介(状态、常用方法)
38 0
|
6月前
|
Java 调度
10分钟从源码级别搞懂AQS(AbstractQueuedSynchronizer)
10分钟从源码级别搞懂AQS(AbstractQueuedSynchronizer)
|
安全 Java 大数据
深入探究 ReentrantLock 的应用和原理
深入探究 ReentrantLock 的应用和原理
169 0
深入探究 ReentrantLock 的应用和原理
|
存储 安全 Java
JUC并发编程(JUC核心类、TimeUnit类、原子操作类、CASAQS)附带相关面试题
1.JUC并发编程的核心类,2.TimeUnit(时间单元),3.原子操作类,4.CAS 、AQS机制
62 0
|
机器学习/深度学习 安全 Java
java并发原理实战(10)--AQS 和公平锁分析
java并发原理实战(10)--AQS 和公平锁分析
133 0
java并发原理实战(10)--AQS 和公平锁分析
|
存储 安全
J.U.C的核心基础内容之AQS源码详解,建议收藏哦!!!
我们来开始今天的内容,首先我们来看下AQS是什么,全称是 AbstractQueuedSynchronizer 翻译过来就是【抽象队列同步】对吧。通过名字我们也能看出这是个抽象类
J.U.C的核心基础内容之AQS源码详解,建议收藏哦!!!
|
安全
AQS原理简介(下)
AQS原理简介(下)
128 0
AQS原理简介(下)