AQS-ReentrantLock.lock 源码

ReentrantLock lock = new ReentrantLock();
lock.lock(); // 默认为非公平锁
final void lock() {
        acquire(1);
    }
    
    // AbstractQueuedSynchronizer里面的方法
    public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }
 // 1.1 tryAcquire 具体子类实现 ReentrantLock.NonfairSync
    protected final boolean tryAcquire(int acquires) {
        return nonfairTryAcquire(acquires);
    }
    // 先尝试去获取一次锁。【CHL队列里面可能还有其他线程等待,这里可以体现出非公平性。】
    final boolean nonfairTryAcquire(int acquires) {
       final Thread current = Thread.currentThread();
        int c = getState();
        if (c == 0) { // 若状态刚好为0,则尝试获取锁。
            if (compareAndSetState(0, acquires)) {
                setExclusiveOwnerThread(current);
                return true;
            }
        }
        else if (current == getExclusiveOwnerThread()) { // 若当前线程持有锁,则直接状态值+1
            int nextc = c + acquires; 
            if (nextc < 0) // overflow
                throw new Error("Maximum lock count exceeded");
            setState(nextc);
            return true;
        }
        return false;
    }
	// 1.2 新增一个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.prev = pred; // 新增节点的前置节点 指向尾节点
            if (compareAndSetTail(pred, node)) { // 比较替换的方式将尾节点指向当前新建的节点
                pred.next = node; // 上一个尾节点的下个节点指向当前新建的节点
                return node; // 返回当前节点
            }
        }
        enq(node); // 若尾节点为空,即当前队列为空
        return node;
    }
    // 队列为空时,新建一个节点,并将头结点尾节点指向新建节点。并将当前节点设置为尾节点,返回当前接的前置节点
    private Node enq(final Node node) {
    	// 开始自旋
        for (;;) {
        	// 第一次尾节点为空
            Node t = tail;
            if (t == null) { // Must initialize
            	// 头结点 = 尾节点 = 新建一个节点
                if (compareAndSetHead(new Node()))
                    tail = head;
            } else {
            	// 当尾节点不为空时,当前节点的前置节点指向尾节点
                node.prev = t;
                // 比较并替换当前节点为尾节点,若替换成功,则上一个尾节点的下一个节点指向最新尾节点(即为当前节点)。并返回当前节点的前置节点
                if (compareAndSetTail(t, node)) {
                    t.next = node;
                    return t;
                }
            }
        }
    }

// 1.3 节点增加到等待队列中
	final boolean acquireQueued(final Node node, int arg) {
        boolean failed = true;
        try {
            boolean interrupted = false;
            // 自旋
            for (;;) {
                final Node p = node.predecessor(); // 获取当前节点的前置节点
                if (p == head && tryAcquire(arg)) { // 若前置节点为头节点,尝试再次获取锁,若获取成功,则将当前节点设置为头节点
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return interrupted;
                }
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt()) 
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }
    private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
        int ws = pred.waitStatus;
        if (ws == Node.SIGNAL) // 若前置节点状态值=-1 则表示,可以直接阻塞
            /*
             * This node has already set status asking a release
             * to signal it, so it can safely park.
             */
            return true;
        if (ws > 0) { // 若前置状态的值 > 0 ,则表示有取消的节点,依次向前找到没有取消的节点,并将改节点的next节点指向当前节点
            /*
             * Predecessor was cancelled. Skip over predecessors and
             * indicate retry.
             */
            do {
                node.prev = pred = pred.prev;
            } while (pred.waitStatus > 0);
            pred.next = node;
        } else {
            /*
             * waitStatus must be 0 or PROPAGATE.  Indicate that we
             * need a signal, but don't park yet.  Caller will need to
             * retry to make sure it cannot acquire before parking.
             */
             // 将节点状态设置为-1
            compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
        }
        return false;
    }
    
    // LockSupport方法阻塞当前线程。
    private final boolean parkAndCheckInterrupt() {
        LockSupport.park(this);
        return Thread.interrupted();
    }
上一篇:Java并发之AQS原理剖析


下一篇:机器学习中分类任务的常用评估指标和python代码实现