AbstractQueuedSynchronizer源码分析(一):AbstractOwnableSynchronizer和Node

1、父类:AbstractOwnableSynchronizer

在AbstractOwnableSynchronizer中只有一个属性和对其的get()和set()方法。
exclusiveOwnerThread:这个属性表明在独占模式下,拥有锁的线程。AOS和子类AQS并不会使用这个属性,而其子类可以在通过维护该属性来控制线程访问控制权。

public abstract class AbstractOwnableSynchronizer
    implements java.io.Serializable {

    private static final long serialVersionUID = 3737899427754241961L;
	/** 空构造函数供子类使用。 */
    protected AbstractOwnableSynchronizer() { }
	/** 独占模式,拥有同步状态的线程 */
    private transient Thread exclusiveOwnerThread;

    protected final void setExclusiveOwnerThread(Thread thread) {
        exclusiveOwnerThread = thread;
    }

    protected final Thread getExclusiveOwnerThread() {
        return exclusiveOwnerThread;
    }
}

2、AbstractQueuedSynchronizer的静态内部类Node

Node持有一个线程,并在表示该线程在同步器等待队列中的状态。直至其线程获得了锁,就会释放这个Node节点。
Node属性介绍

字段名称 类型 默认值 作用
SHARED Node new Node() 标识节点以共享模式等待
EXCLUSIVE Node null 标识节点以独占模式等待
CANCELLED int 1 标识线程已经被取消
SIGNAL int -1 标识当前节点的后继节点的线程需要取消阻塞
CONDITION int -2 标识线程由于阻塞而处于等待状态
PROPAGATE int -3 标识处于共享状态下,下一次的acquire需要无条件地传播
waitStatus int 0 标识处于初始状态
prev Node null 当前节点的前驱节点
next Node null 当前节点的后继节点

Node方法介绍

方法名 返回值 作用
isShared() boolean 判断该节点是否共享模式
predecessor() 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;

		 /** 标识处于共享状态下,下一次的acquire需要无条件地传播 */
        static final int PROPAGATE = -3;

		 /** 标识处于初始状态 */
        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;
        }
    }

3、AbstractQueuedSynchronizer的基本数据结构

  1. AQS的基本数据结构以Node节点组成的等待队列,可以理解为“等待锁的线程队列”。
  2. 每个Node节点都持有一个“waitStatus”字段,用于标记线程当前的行为。
  3. head节点的下一个节点会尝试acquire,因为head节点是一个dummy节点,不持有线程。
  4. 入队操作是直接将节点加入队列尾部。
  5. 线程获取锁后,Node节点释放线程,并设置为head头结点。
    下面图示表示了AQS的数据结构
    同步器结构

4、AbstractQueuedSynchronizer的public方法初识

public修饰的方法是提供给同步工具类使用的,如ReentrantLock、ReentrantReadWriteLock等同步工具使用的。

方法 返回值 作用
acquire(int arg) void 不响应中断的获取独占锁
acquireInterruptibly(int arg) void 响应中断的获取独占锁
tryAcquireNanos(int arg, long nanosTimeout) boolean //TODO
release(int arg) boolean 释放独占锁
acquireShared(int arg) void 不响应中断的获取共享锁
acquireSharedInterruptibly(int arg) void 响应中断的获取共享锁
tryAcquireSharedNanos(int arg, long nanosTimeout) boolean //TODO
releaseShared(int arg) boolean 释放共享锁

上面是对后面的内容进行铺垫,后续章节主要介绍锁是如何对同步状态进行管理。以上这个几个方法是获取同步状态和释放同步状态的核心方法。会逐一对其逻辑进行详细剖析。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章