AQS

java.util.concurrent.locks.AbstractQueuedSynchronizer,译为形象队列式同步器
AQS 提供了原子式治理同步状态、阻塞和唤醒线程性能以及期待队列模型的简略框架;

AQS 蕴含了一个虚构的Node双向链表(即期待队列),由 volatile 润饰的头&尾节点,以及同步状态标记state,节点期待状态标记waitStatus,和以后线程信息

AQS 提供了共享锁与独占锁的反对

独占锁

同一个时刻只能被一个线程占有,如ReentrantLock,ReentrantWriteLock等,其中又蕴含了
偏心锁与非偏心锁

共享锁

同一时间点能够被多个线程同时占有,如ReentrantReadLock,Semaphore等

偏心锁 & 非偏心锁

初始化

    // 偏心锁    ReentrantLock lock = new ReentrantLock(true);    // 非偏心锁    ReentrantLock lock = new ReentrantLock();    ReentrantLock lock = new ReentrantLock(false);

加锁过程

java.util.concurrent.locks.ReentrantLock.FairSync#lock

    final void lock() {        // 尝试将以后锁的状态置为1 即为加锁胜利        acquire(1);    }    public final void acquire(int arg) {    /**     * 尝试加锁 tryAcquire = true 则加锁胜利     * 加锁失败时进入后续的期待流程 acquireQueued     * acquireQueued 将有限循环获取锁     * 若获取到锁间接开始执行      * 或前节点成为头部 本人行将执行 则临时挂起     */     if (!tryAcquire(arg) &&        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))        selfInterrupt();    }
1.尝试加锁(偏心锁模式)
    /**     * 尝试获取锁 设置锁状态 锁状态的数值理论为获取锁线程的加锁的次数(可重入)     * 返回true为加锁胜利 false为失败     */    protected final boolean tryAcquire(int acquires) {        // 以后线程        final Thread current = Thread.currentThread();        // 获取以后锁的状态        int c = getState();        // 以后锁状态为0 则为能够加锁        if (c == 0) {            /**             * 非偏心锁模式将不会判断队列是否有其余节点 会间接尝试获取锁             * hasQueuedPredecessors = false              * 则期待队列中没有其余线程              * 即以后线程是下一个该当获取锁的线程             */             if (!hasQueuedPredecessors() &&                 /**                 * 思考到有其余线程同时判断结束                 * 故进行CAS操作 尝试批改锁状态                 */                 compareAndSetState(0, acquires)) {                // 前两步都已胜利 则将以后线程设置为持有锁的线程                setExclusiveOwnerThread(current);                return true;            }        }        // 以后锁状态不为0 且持有锁的线程是以后线程 则间接重入        else if (current == getExclusiveOwnerThread()) {            // 设置以后锁状态+1 即以后线程总共上锁的次数            int nextc = c + acquires;            // 若上锁次数为负 实为上锁次数越界            if (nextc < 0)                throw new Error("Maximum lock count exceeded");            setState(nextc);            return true;        }        return false;    }
判断是否期待队列中是否有其余线程(非偏心锁没有此步骤)
public final boolean hasQueuedPredecessors() {    // The correctness of this depends on head being initialized    // before tail and on head.next being accurate if the current    // thread is first in queue.    Node t = tail; // Read fields in reverse initialization order    Node h = head;    Node s;    /**      * 队列头部 与 队列尾部元素 不相等      * 且头部后一个元素不为空 或头部后一个期待线程不是以后线程     * 阐明队列中至多有其余的线程在期待     */    return h != t &&        ((s = h.next) == null || s.thread != Thread.currentThread());}
CAS操作进行锁状态变更
protected final boolean compareAndSetState(int expect, int update) {    // See below for intrinsics setup to support this    return unsafe.compareAndSwapInt(this, stateOffset, expect, update);}

2.加锁失败 进入期待队列

/** * 将以后线程构建为期待队列的元素 即Node  * 下文将用Node示意以后线程构筑的期待队列元素 * 将该Node期待的线程设置为以后锁的持有线程 * CAS操作 尝试将以后Node 设置为队列尾部元素 */ private Node addWaiter(Node mode) {    Node node = new Node(Thread.currentThread(), mode);    // Try the fast path of enq; backup to full enq on failure    Node pred = tail;    // 判断以后尾部元素 是否为空    if (pred != null) {        // 尾部不为空 设置尾部元素为以后线程Node 的前节点元素        node.prev = pred;        // 尝试将以后线程Node设置成尾部元素        if (compareAndSetTail(pred, node)) {            // 胜利后 批改旧的队尾元素的后一个节点为以后Node            pred.next = node;            return node;        }    }    enq(node);    return node;}    final boolean acquireQueued(final Node node, int arg) {    boolean failed = true;    try {        boolean interrupted = false;        // 以后Node会在此处有限循环 直到前节点成为头部 本人获取到锁才返回        for (;;) {            // 获取以后Node的前节点            final Node p = node.predecessor();            // 若以后节点的前节点已成为队列头部 则再次尝试加锁            if (p == head && tryAcquire(arg)) {                // 胜利后 设置以后Node为头部元素                setHead(node);                p.next = null; // help GC                // 此时已获取到锁 故无需再设置本人为中断状态                 // 进入队列后果则为失败                failed = false;                return interrupted;            }            /**             * shouldParkAfterFailedAcquire 判断以后线程是否可能挂起             * 革除队列中已勾销的节点             * 判断为true 则能够挂起             */             if (shouldParkAfterFailedAcquire(p, node) &&                /**                 * parkAndCheckInterrupt 执行挂起                 * 并返回以后线程是否有过中断请求                 */                parkAndCheckInterrupt())                /**                 * 以后线程在期待过程中无奈响应中断 直到获取到锁                 * 如果在整个期待过程中被中断过 则interrupted = true                 * acquireQueued最终返回true 否则返回false                  * 并在外层响应中断                 * 须要其余线程调用以后线程的interrupt()办法                 */                interrupted = true;        }    } finally {        if (failed)            cancelAcquire(node);    }}

参考资料:
https://blog.csdn.net/Java_zh...
https://blog.csdn.net/Leon_Ji...
https://blog.csdn.net/yy_dieg...