手撕AQS源码第一弹 -- AQS的继承体系,内部类,成员变量

AQS的继承体系,内部类,成员变量

父类和父接口

AbstractQueuedSynchronizer继承了AbstractOwnableSynchronizer,实现类序列化接口。而AbstractOwnableSynchronizer主要就是一个成员变量exclusiveOwnerThread,表示当前持锁的线程对象,然后就是get set方法,是个很简单的抽象类。

public abstract class AbstractQueuedSynchronizer
    extends AbstractOwnableSynchronizer
    implements java.io.Serializable {...}

AbstractOwnableSynchronizer

public abstract class AbstractOwnableSynchronizer
    implements java.io.Serializable {
	//表示当前持有锁的线程
    private transient Thread exclusiveOwnerThread;

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

可以看一下AbstractQueuedSynchronizer的继承体系图,结构还是比较简单的。

image-20200920101917723

AQS的内部类

Node

AQS底层是个双向链表,每个节点都是一个Node,我们看到他有几个属性:

  • Node prev 表示该节点的前面的节点
  • Node next 表示该节点的后面一个节点
  • Thread thread 表示每个节点都记录一个线程
  • Node nextWaiter 添加进队列相关
  • int waitStatus 记录线程当前状态,有一些状态值,比如-1是睡着了。
static final class Node {

    volatile int waitStatus;

    volatile Node prev;

    volatile Node next;
    
    volatile Thread thread;

    Node nextWaiter;
	
    Node(Thread thread, Node mode) {     
        this.nextWaiter = mode;
        this.thread = thread;
    }

    Node(Thread thread, int waitStatus) { 
        this.waitStatus = waitStatus;
        this.thread = thread;
    }
}

ConditionObject

ConditionObject是AQS中的内部类,提供了条件锁的同步实现,实现了Condition接口,并且实现了其中的await(),signal(),signalALL()等方法。
ConditionObject主要是为并发编程中的同步提供了等待通知的实现方式,可以在不满足某个条件的时候挂起线程等待。直到满足某个条件的时候在唤醒线程。

public class ConditionObject implements Condition, java.io.Serializable {

        private static final long serialVersionUID = 1173984872572414699L;
        /** First node of condition queue. */
        private transient Node firstWaiter;
        /** Last node of condition queue. */
        private transient Node lastWaiter;
}

AQS的成员变量

很庆幸,AQS的成员变量并不多,很好理解,包括常量就这么几个,主要就是AQS队列相关的成员变量:

  • Node head 队列的头指针,默认是null
  • Node tail 队列是尾指正,默认是null
  • int state 记录了当前锁的状态,0表示锁是自由态,如果是重入锁,state可以大于1,如果不是,state只能是0和1,看具体实现了类了。
  • spinForTimeoutThreshold 旋转超时阈值,我们的AQS中有一些方法允许我们传入一个时间单位TimeUnit,给AQS等待队列加一些时间的控制管理。
  • unsafe 这个类是CAS的核心,其包装了很多CAS操作以及Java直接操作内存的一下native方法。
  • 其他成员变量 用于记录一些CAS操作要用的一些交换值。
static final long spinForTimeoutThreshold = 1000L;

private transient volatile Node head;

private transient volatile Node tail;

private volatile int state;

private static final Unsafe unsafe = Unsafe.getUnsafe();
    private static final long stateOffset;
    private static final long headOffset;
    private static final long tailOffset;
    private static final long waitStatusOffset;
    private static final long nextOffset;

小结

阅读AQS源码其实要从他的实现类才能看到其工作流程,所以他是个Abstract起头的类名,我们的常见的ReentrantLock,ReentrantReadWriterLock都是他的子类。

可以看到AQS是在JUC的locks包中的,而我们的Lock包也就这么几个类,但是理解起来还是要耗费一些时间的。

image-20200920103720199

©️2020 CSDN 皮肤主题: 书香水墨 设计师:CSDN官方博客 返回首页