AQS源码分析

AQS

Posted by changechenhao on March 12, 2019

前言

AQSSemaphoreReentrantReadWriteLockReentrantLockCountDownLatch等并发类 底层的实现,点开上面说的并发类的源码我们可以看到,它们自身的实现很少,基本上都是在AQS下实现的。面试的 时候上述所说的并发工具都会问到,但一般我们只关注它们的用法与区别,很少关注其实现。今天这篇文章,我们以 ReentrantLock为基础,来看AQS是如何实现的ReentrantLock

AQS

AQS

AQS源码分析

Node 节点

锁的获取与释放

enq 与 addWaiter

/**
 * Inserts node into queue, initializing if necessary. See picture above.
 * @param node the node to insert
 * @return node's predecessor
 */
private Node enq(Node node) {
    for (;;) {
        // 获取尾部节点
        Node oldTail = tail;
        // 
        if (oldTail != null) {
            //设置插入节点的pre节点为旧节点
            node.setPrevRelaxed(oldTail);
            //CAS 设置尾部节点,循环到成功为止
            if (compareAndSetTail(oldTail, node)) {
                //设置旧节点next为插入的节点node
                oldTail.next = node;
                //返回旧节点
                return oldTail;
            }
        } else {
            //尾部节点为null,初始化队列
            initializeSyncQueue();
        }
    }
}

 /**
 * Creates and enqueues node for current thread and given mode.
 *
 * @param mode Node.EXCLUSIVE for exclusive, Node.SHARED for shared
 * @return the new node
 */
private Node addWaiter(Node mode) {
    Node node = new Node(mode);

    for (;;) {
        Node oldTail = tail;
        if (oldTail != null) {
            node.setPrevRelaxed(oldTail);
            if (compareAndSetTail(oldTail, node)) {
                oldTail.next = node;
                return node;
            }
        } else {
            initializeSyncQueue();
        }
    }
}

enqaddWaiter 业务逻辑相同,只是返回的节点不同,enq 返回旧的尾节点,addWaiter 返回当前节点。