Java基础建设 4-AQS源码分析

一、AQS分析

1.原理概述

AQS全称`AbstractQueuedSynchronizer`,java中几乎所有锁均是基于AQS做的实现,AQS原理是基于CLH算法的
双向队列,AQS提供队列的基础操作和锁判定,子类提供上层封装,实现诸如公平/非公平锁、try之类操作、基于互斥共享锁实现读写锁等

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;
        /** 节点状态:当前节点在条件队列,当条件队列的节点被singal后,会由CONDITION变为出事状态0,再转为SIGNAL状态并进入到同步队列 */
        static final int CONDITION = -2;
        /** 节点状态:传播状态,用在读写锁场景,只能用于头结点,表示头结点的状态能够传递下去 */
        static final int  PROPAGATE  = -3;

        /**
         * 节点状态
         */
        volatile int waitStatus;

        /**
         * 同步队列——前节点
         */
        volatile Node prev;

        /**
         * 同步队列——后节点
         */
        volatile Node next;

        /**
         * 当前节点对应的线程
         */
        volatile Thread thread;

        /**
         * 当前节点在条件队列下一个等待节点
         */
        Node nextWaiter;
}
  • Head/Tail
    条件队列的头尾节点,Head节点是已经获取到锁的节点,Tail节点为队尾节点,每次查询应当唤醒节点的时候,都是从队尾节点开始扫描
  • state
    AQS的同步队列状态,默认为0,是否锁定通过其来判定,加锁过程是对其累加,解锁是对其进行减去加锁累加的值,在重入锁过程中
  • xxOffset(stateOffset/headOffset...)
    记录相关属性的地址偏移量,并通过CAS操作对其进行修改

3.同步队列之acquire流程

image.png

4.同步队列之release流程

image.png

5.条件队列之await流程

image.png

6.条件队列之signal流程

image.png

7.同步队列与条件队列

image.png

二、总结

1.AQS的同步队列为等待获取锁的队列,Head节点为已经获得到锁的节点,head节点release后,通过unpark唤醒后续等待节点,head节点继续for循环,通过tryAcqure加锁成功后,将自己设置为同步队列的新的头结点
2.AQS通过state和exclusiveOwnerThread来实现加解锁和可重入锁

你可能感兴趣的:(Java基础建设 4-AQS源码分析)