Java Abstract Synchronization Queue AbstractQueuedSynchronizer

table of Contents

1. Introduction to AbstractQueuedSynchronizer

2. AQS internal structure

3. State information

4. Inner class Node

4.1 Node source code

4.2 CAS operations on Node

4.3 Node operations in the queue

5. Inner class ConditionObject

5.1 await () method

5.2 signal () method

6. Methods of acquiring and releasing resources

6.1 Exclusive method

6.2 Sharing method


1. Introduction to AbstractQueuedSynchronizer

Abstract synchronization queue AbstractQueuedSynchronizer, referred to as AQS, it is to achieve blocking locks and other synchronization components based on first-in first-out (FIFO) waiting queue.

The underlying implementation of locks in concurrent packages (such as ReentrantLock  ) is implemented using AQS.

 

2. AQS internal structure

i. AQS inherited from AbstractOwnableSynchronizer

ii. Class ConditionObject mainly provides a condition, subclass determines whether to support exclusive mode

iii. Class Node, as a first-in first-out (FIFO) blocking each node in the queue

 

3. State information

AQS maintains a single state information state, which can be modified by getState (), setState (int newState), compareAndSetState (int expect, int update) methods.

private static final Unsafe unsafe = Unsafe.getUnsafe();
// 状态信息
private volatile int state;
// 返回当前的状态值。该操作拥有 volatile 读的内存语义
protected final int getState() {
    return state;
}
//设置状态值
protected final void setState(int newState) {
    state = newState;
}
// 通过 unsafe 类原子的设置同步状态值为给定的 update 值,设置成功后返回true,否则返回false
protected final boolean compareAndSetState(int expect, int update) {
    return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}

Examples of state functions:

In ReentrantLock , state represents the number of reentrant times the current thread has acquired the lock.

In ReentrantReadWriteLock, the high 16 bits of state indicate the number of times the read lock is acquired, and the low 16 indicates the number of reentrant times for the thread that acquired the write lock.

 

4. Inner class Node

4.1 Node source code

static final class Node {
    // 标记符,共享模式下的等待节点
    static final Node SHARED = new Node();
    // 标记符,独占模式下等待节点
    static final Node EXCLUSIVE = null;
    
    /**
      * 等待状态值
      *   1 表示线程已经被取消
      * -1 表示一个后继节点的线程需要唤醒
      * -2 表示线程等待在某种条件下
      * -3 表示下一次共享式获取状态的操作应该无条件的传播
      */
    static final int CANCELLED =  1;
    static final int SIGNAL    = -1;
    static final int CONDITION = -2;
    static final int PROPAGATE = -3;

   // 状态字段,取上述 4 个状态值。值为 0,表示非以上状态
    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() { 
    }
    // addWaiter 使用。给线程添加等待模型
    Node(Thread thread, Node mode) {
        this.nextWaiter = mode;
        this.thread = thread;
    }
    // Condition 使用,给线程添加等待条件
    Node(Thread thread, int waitStatus) {
        this.waitStatus = waitStatus;
        this.thread = thread;
    }
}

4.2 CAS operations on Node

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;

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); }
}

/**
 * 使用 unsafe 类对 Node 进行原子更新。如果当前状态值等于预期值,则以原子方式将同步状态设置为给定的更新值。
 */
private final boolean compareAndSetHead(Node update) {
    return unsafe.compareAndSwapObject(this, headOffset, null, update);
}

private final boolean compareAndSetTail(Node expect, Node update) {
    return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
}
private static final boolean compareAndSetWaitStatus(Node node,
                                                        int expect,
                                                        int update) {
    return unsafe.compareAndSwapInt(node, waitStatusOffset,
                                    expect, update);
}
private static final boolean compareAndSetNext(Node node,
                                                Node expect,
                                                Node update) {
    return unsafe.compareAndSwapObject(node, nextOffset, expect, update);
}

4.3 Node operations in the queue

/**
* 将节点加入队列,必要时进行初始化
*/
private Node enq(final Node node) {
    for (;;) {
        Node t = tail;
        if (t == null) {
            // 尾结点为空,需要初始化
            if (compareAndSetHead(new Node()))
                tail = head;
        } else {
            // 尾结点不为空,unsafe进行插入节点
            node.prev = t;
            if (compareAndSetTail(t, node)) {
                t.next = node;
                return t;
            }
        }
    }
}
/**
 * 为当前线程设置指定模式。并加入队列
 */
private Node addWaiter(Node mode) {
    Node node = new Node(Thread.currentThread(), mode);
    Node pred = tail;
    if (pred != null) {
        node.prev = pred;
        if (compareAndSetTail(pred, node)) {
            pred.next = node;
            return node;
        }
    }
    enq(node);
    return node;
}
/**
 * 设置头结点
 */
private void setHead(Node node) {
    head = node;
    node.thread = null;
    node.prev = null;
}
/**
 * 如果存在后继节点则进行唤醒操作
 */
private void unparkSuccessor(Node node) {
    int ws = node.waitStatus;
    if (ws < 0)
        compareAndSetWaitStatus(node, ws, 0);
    Node s = node.next;
    if (s == null || s.waitStatus > 0) {
        s = null;
        for (Node t = tail; t != null && t != node; t = t.prev)
            if (t.waitStatus <= 0)
                s = t;
    }
    if (s != null)
        LockSupport.unpark(s.thread);
}

 

5. Inner class ConditionObject

ConditionObject implements the Condition interface. The Condition object is created by the Lock object.

/** 
 * 等待队列中的头结点
 */
private transient Node firstWaiter;
/** 
 * 等待队列中的尾结点
 */
private transient Node lastWaiter;

Two methods at the core of ConditionObject: await () and signal ()

5.1 await () method

  • The current thread enters a waiting state until it is notified or interrupted
  • The current thread will enter the running state and return from the await () method:
    • Other threads call the Condition's signal () or signalAll () method
    • Other threads call the interrupt () method to interrupt the current thread
    • If the waiting thread returns from the await () method, the thread has acquired the lock corresponding to the Condition object

5.2 signal () method

Wake up a thread waiting on the Condition, which must acquire the lock associated with the Condition before returning from the wait method

signal () is to wake up a thread, and signalAll () is to wake up all waiting threads

 

6. Methods of acquiring and releasing resources

Exclusive way: acquire (int arg), acquireInterruptibly (int arg), release (int arg)

Sharing method: acquireShared (int arg), acquireSharedInterruptibly (int arg), releaseShared (int arg) 

6.1 Exclusive method

/**
 * 获取独享锁
 * tryAcquire 需要子类重写方法
 */
public final void acquire(int arg) {
        // 尝试获取锁,获取成功返回 true,否则返回 false
    if (!tryAcquire(arg) &&  
        // 没有获取则加入队列尾部,并通过 LockSupport.park(this)挂起自己
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) 
        // 进行自我中断
        selfInterrupt(); 
}
// 线程自我中断
static void selfInterrupt() {
    Thread.currentThread().interrupt();
}
/**
 * 试着释放当前线程持有的独占锁并唤醒后继节点
 */
public final boolean release(int arg) {
    // tryRelease 独享式释放同步状态,需要子类重写
    if (tryRelease(arg)) { 
        Node h = head;
        if (h != null && h.waitStatus != 0)
            unparkSuccessor(h);
        return true;
    }
    return false;
}
/**
 * 获取独占锁的可中断模式
 */
public final void acquireInterruptibly(int arg)
            throws InterruptedException {
    if (Thread.interrupted())
        // 当前线程如果中断,则抛出中断异常
        throw new InterruptedException();
    if (!tryAcquire(arg)) // 尝试获取锁
        // 获取锁失败,则调用 doAcquireInterruptibly 获取独享锁的可中断模式
        doAcquireInterruptibly(arg);
}

6.2 Sharing method

The sharing method is similar to the exclusive method

public final void acquireShared(int arg) {
    if (tryAcquireShared(arg) < 0)
        // 获取共享锁的不中断模式
        doAcquireShared(arg);
}
public final void acquireSharedInterruptibly(int arg)
            throws InterruptedException {
    if (Thread.interrupted())
        throw new InterruptedException();
    if (tryAcquireShared(arg) < 0)
        doAcquireSharedInterruptibly(arg);
}
public final boolean releaseShared(int arg) {
    if (tryReleaseShared(arg)) {
        doReleaseShared();
        return true;
    }
    return false;
}

 

 

 

 

Published 7 original articles · won 3 · views 308

Guess you like

Origin blog.csdn.net/sl285720967/article/details/105588703
Recommended