Java 抽象同步队列 AbstractQueuedSynchronizer

目录

1. AbstractQueuedSynchronizer 介绍

2. AQS 内部结构

3. 状态信息 state

4. 内部类 Node

4.1 Node 类源码

4.2 对 Node 的 CAS 操作

4.3 队列中的 Node 操作

5. 内部类 ConditionObject

5.1 await() 方法

5.2 signal() 方法

6. 获取和释放资源的方法

6.1 独享方式

6.2 共享方式


1. AbstractQueuedSynchronizer 介绍

抽象同步队列 AbstractQueuedSynchronizer ,简称 AQS,它是实现阻塞锁和其他基于先入先出(FIFO)等待队列的同步组件。

并发包中锁的底层实现(如 ReentrantLock )的底层实现就是使用 AQS 实现的。

2. AQS 内部结构

i. AQS 继承自 AbstractOwnableSynchronizer

ii. 类 ConditionObject 主要提供一种条件,由子类决定是否支持独占模式

iii. 类 Node,作为先入先出(FIFO)阻塞队列里面的每个节点

3. 状态信息 state

AQS 维持了一个单一的状态信息 state,可通过 getState()、setState(int newState)、compareAndSetState(int expect, int update) 方法来修改 state 的值。

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

state 作用举例:

ReentrantLock 中,state 表示当前线程获取锁的可重入次数。

ReentrantReadWriteLock 中,state 高 16 位表示获取读锁的次数,低 16 为表示获取写锁的线程的可重入次数。

4. 内部类 Node

4.1 Node 类源码

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 对 Node 的 CAS 操作

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 操作

/**
* 将节点加入队列,必要时进行初始化
*/
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. 内部类 ConditionObject

ConditionObject 实现了 Condition 接口。Condition 对象是由 Lock 对象创建的。

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

ConditionObject 核心的两个方法:await() 、signal()

5.1 await() 方法

  • 当前线程进入等待状态,知道被通知(signal)或中断
  • 当前线程将进入运行状态且从 await() 方法返回的情况:
    • 其他线程调用该 Condition 的 signal() 或 signalAll() 方法
    • 其他线程调用 interrupt() 方法中断当前线程
    • 如果等待线程从 await() 方法返回,则该线程已经获取了 Condition 对象所对应的锁

5.2 signal() 方法

唤醒一个等待在 Condition 上的线程,该线程从等待方法返回前必须获得与 Condition 相关联的锁

signal() 为唤醒一个线程,signalAll() 为唤醒所有等待的线程

6. 获取和释放资源的方法

独享方式:acquire(int arg)、acquireInterruptibly(int arg)、release(int arg)

共享方式:acquireShared(int arg) 、acquireSharedInterruptibly(int arg)、releaseShared(int arg) 

6.1 独享方式

/**
 * 获取独享锁
 * 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 共享方式

共享方式与独享方式类似

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;
}
发布了7 篇原创文章 · 获赞 3 · 访问量 308

猜你喜欢

转载自blog.csdn.net/sl285720967/article/details/105588703