[JAVA]JUC

AQS

AQS是实现锁机制的基础,特德内部封装了包括锁的获取、释放、以及等待队列。

  • 一个锁(以排他锁为例)的基本功能就是获取锁、释放锁。
  • 当锁被占用时,其他线程来争抢就会进入等待队列。
  • 等待队列是由双向链表实现的,每个等待线程下的线程都可以被封装进节点中闭关放入双向列表中,而对于双向链表是以队列的形式进行操作的。

  • AQS中有一个head字段和一个tail字段分别记录双向链表的头结点和尾结点,而之后的一系列操作都是围绕此队列来进行的。我们先来了解一下每个结点都包含了哪些内容:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    //每个处于等待状态的线程都可以是一个节点,并且每个节点是有很多状态的
    static final class Node {
    //每个节点都可以被分为独占模式节点或是共享模式节点,分别适用于独占锁和共享锁
    static final Node SHARED = new Node();
    static final Node EXCLUSIVE = null;

    //等待状态,这里都定义好了
    //唯一一个大于0的状态,表示已失效,可能是由于超时或中断,此节点被取消。
    static final int CANCELLED = 1;
    //此节点后面的节点被挂起(进入等待状态)
    static final int SIGNAL = -1;
    //在条件队列中的节点才是这个状态
    static final int CONDITION = -2;
    //传播,一般用于共享锁
    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() {
    }

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

    Node(Thread thread, int waitStatus) {
    this.waitStatus = waitStatus;
    this.thread = thread;
    }
    }
  • 在一开始的时候,head和tail都是null,state为默认值0:

    1
    2
    3
    4
    5
    private transient volatile Node head;

    private transient volatile Node tail;

    private volatile int state;
  • 不用担心双向链表不会进行初始化,初始化是在实际使用时才开始的,先不管,我们接着来看其他的初始化内容:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    //直接使用Unsafe类进行操作
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    //记录类中属性的在内存中的偏移地址,方便Unsafe类直接操作内存进行赋值等(直接修改对应地址的内存)
    private static final long stateOffset; //这里对应的就是AQS类中的state成员字段
    private static final long headOffset; //这里对应的就是AQS类中的head头结点成员字段
    private static final long tailOffset;
    private static final long waitStatusOffset;
    private static final long nextOffset;

    static { //静态代码块,在类加载的时候就会自动获取偏移地址
    try {
    stateOffset = unsafe.objectFieldOffset
    (AbstractQueuedSynchronizer.class.getDeclaredField("state"));
    headOffset = unsafe.objectFieldOffset
    (AbstractQueuedSynchronizer.class.getDeclaredField("head"));
    tailOffset = unsafe.objectFieldOffset
    (AbstractQueuedSynchronizer.class.getDeclaredField("tail"));
    waitStatusOffset = unsafe.objectFieldOffset
    (Node.class.getDeclaredField("waitStatus"));
    nextOffset = unsafe.objectFieldOffset
    (Node.class.getDeclaredField("next"));

    } catch (Exception ex) { throw new Error(ex); }
    }

    //通过CAS操作来修改头结点
    private final boolean compareAndSetHead(Node update) {
    //调用的是Unsafe类的compareAndSwapObject方法,通过CAS算法比较对象并替换
    return unsafe.compareAndSwapObject(this, headOffset, null, update);
    }

    //同上,省略部分代码
    private final boolean compareAndSetTail(Node expect, Node update) {

    private static final boolean compareAndSetWaitStatus(Node node, int expect, int update) {

    private static final boolean compareAndSetNext(Node node, Node expect, Node update) {