AQS AbstractQueuedSynchronizer底层原理

AQS AbstractQueuedSynchronizer底层原理

AQS AbstractQueuedSynchronizer底层原理(1)

本文对reentrantLock底层代码中的方法调用进行分析.

ReentrantLock类

public void lock() {
    sync.lock(); // sync是抽象类,所以去找到sync的实现类的lock方法.        1 ---> 2
}

// 空参构造创建的是非公平锁. 所以调用的是NonfairSync中的lock方法.
public ReentrantLock() {
        sync = new NonfairSync();
    }

// sync是ReentrantLock的内部类
abstract static class Sync extends AbstractQueuedSynchronizer {
    
    abstract void lock();
    
    ...
}

// NonfairSync依旧是个内部类.
static final class NonfairSync extends Sync {
// 2
        final void lock() {
            if (compareAndSetState(0, 1))        // 上来直接cas操作 抢锁
                setExclusiveOwnerThread(Thread.currentThread());  // 抢成功了 设置当前线程获得排他锁
            else
                acquire(1);  // 已经有线程持有锁 没抢到 才调用acquire ,如果是公平锁则直接acquire.  2--->3
        }

// 4 非公平锁
protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread(); 
            int c = getState();
            if (c == 0) { // 当前线程并未获取到锁
                if (!hasQueuedPredecessors() &&        // 4--->5 阻塞队列是否有前驱? (阻塞队列由aqs实现)
                    compareAndSetState(0, acquires)) { // 尝试获取锁
                    setExclusiveOwnerThread(current); // 获取成功 将此线程设为持有锁状态.
                    return true; // 5--->3 acquire执行结束, lock方法执行完成了
                }
            }
    //当前线程已获取到锁 c!=0 这是重入锁的情况.
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0)
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
    
            return false; // (4到5这步执行失败了 未获取到锁 往下执行到6--7接着往后..)
        }
    }
}
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable {

    // 3 aqs类中acquire方法.
    public final void acquire(int arg) {
        if (!tryAcquire(arg) &&                // 3--->4 非公平锁对tryAcquire方法进行了实现(不同的锁有其具体的实现)
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))//6--->7addWaiter(), 10--->11 acquireQueued()
            selfInterrupt();
    }

    // 5阻塞队列: 若队列为空或无前驱(即对头是当前线程)返回false
    public final boolean hasQueuedPredecessors() {

        Node t = tail; 
        Node h = head;
        Node s;
        return h != t &&    // 如果尾巴等于头 即队列为空 
            ((s = h.next) == null || s.thread != Thread.currentThread()); //队列的头其实是当前线程(重入的情况)
    }

    // 7 (3到4这部获取锁失败 走到了这步)     mode = EXCLUSIVE = null
    // addWaiter 获取锁失败了 进入阻塞队列 等待重新获取锁.
    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)) { // cas操作当前结点设为尾结点.
                pred.next = node;
                return node; // 返回当前结点 (此方法结束 往后执行 10--->11)
            }
        }
        enq(node); //尾巴为空 或  添加至队列失败 进入此方法(保证一定入队  8--->9)
        return node; // 返回当前结点 (此方法结束 往后执行 10--->11)
    }

    // 9
    private Node enq(final Node node) {
        //自旋形式入队,可以看到这里是一个无限循环
        for (;;) {
            Node t = tail;
            if (t == null) {  //这种情况只能说明头结点和尾结点都还没初始化
                if (compareAndSetHead(new Node()))   //初始化头结点和尾结点
                    tail = head;
            } else {
                node.prev = t;
                if (compareAndSetTail(t, node)) {
                    t.next = node;
                    return t;   //只有CAS成功的情况下,才算入队成功,如果CAS失败
                }
            }
        }
    }

    // 11: 获取排队
    final boolean acquireQueued(final Node node, int arg) {
        boolean failed = true;// 是否失败
        try {
            boolean interrupted = false; // 是否被打断
            for (;;) {
                final Node p = node.predecessor();
                //若此节点位于队首(node.prev == head)时,会再次调用tryAcquire方法获取锁,如果获取成功,会返回此过程中是否被中断的值
                if (p == head && tryAcquire(arg)) {   
                    // 对阻塞队列调整↓
                    setHead(node);    //新的头结点设置为当前结点
                    p.next = null; // 原有的头结点没有存在的意义了

                    failed = false;   //没有失败 即成功获取锁
                    return interrupted;   //直接返回等待过程中是否被中断 此方法结束返回10
                }    
                //依然没获取成功,
                //将当前节点的前驱节点等待状态设置为SIGNAL,如果失败将直接开启下一轮循环,直到成功为止,如果成功接着往下 //方法细节看12
                if (shouldParkAfterFailedAcquire(p, node) &&  
//挂起线程进入等待状态,等待被唤醒,如果在等待状态下被中断,那么会返回true,直接将中断标志设为true
//若未被中断就是正常唤醒继续自旋 方法细节看13
                    parkAndCheckInterrupt())  
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node); // 被中断 取消获取
        }
    }

    // 12
    private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
        int ws = pred.waitStatus;
        if (ws == Node.SIGNAL)
            return true;   //已经是SIGNAL,直接true
        if (ws > 0) {   //不能是已经取消的节点,必须找到一个没被取消的
            do {
                node.prev = pred = pred.prev;
            } while (pred.waitStatus > 0);
            pred.next = node;   //直接抛弃被取消的节点
        } else {
            //不是SIGNAL,先CAS设置为SIGNAL(这里没有返回true因为CAS不一定成功,需要下一轮再判断一次)
            compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
        }
        return false;   //返回false,马上开启下一轮循环
    }

    //13
    private final boolean parkAndCheckInterrupt() {
        LockSupport.park(this);
        return Thread.interrupted();
    }

}

你可能感兴趣的:(java程序员aqs)