AQS源码解析

AQS源码分析

场景模拟:

假如有三个线程 A B C , 而A线程先抢到了线程而且将后面的线程阻塞了很长时间

  1. 首先来到ReentrantLock 的 205 行 当前是第一次抢夺线程来到这个方法

final void lock() {
    // state的默认值是0 获取到当前的值比较并交换是否为0如果是就更新为1
    // 因为线程A是第一个来抢夺的所有满足条件
    if (compareAndSetState(0, 1))
        // 进入判断 将当前线程设置为一个排他锁
        setExclusiveOwnerThread(Thread.currentThread());
    else
        acquire(1);
}

至此线程A执行完毕并且 state 的状态变为了 1

 

  1. 当第二个线程B进来抢夺线程同样首先来到这里

    final void lock() {
        // 对state的值比较并交换 如果当前的state值为0就更新为1
        // 因为在A线程占到位置以后就把state的值修改为了 1
        // 所以本次判读失败直接进入else
        if (compareAndSetState(0, 1))
            setExclusiveOwnerThread(Thread.currentThread());
        else
            // 线程B修改state值失败进入else逻辑
            acquire(1);
    }

  1. 点击进入 acquire(1); 方法

    public final void acquire(int arg) { // 当前的arg值为 1 是上一步传入进来的
            // 首先进入到 tryAcquire(arg) 方法
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

  2. 进入到 tryAcquire(arg) 方法 然后来到 nonfairTryAcquire

   final boolean nonfairTryAcquire(int acquires) { // acquires 值为1 是上面方法传入进来的
       final Thread current = Thread.currentThread(); // current 即为当前线程B
       int c = getState();  // c为当前的state 值为1
       if (c == 0) {  // 当前c值为1 所以直接进入else if
           if (compareAndSetState(0, acquires)) {
               setExclusiveOwnerThread(current);
               return true;
           }
       }
       // 来到else if 判断当前的线程是否为 正在执行操作的线程
       // 当前线程为 B 正在执行操作的线程为 A 所以无法进入当前逻辑 直接到最后返回false
       else if (current == getExclusiveOwnerThread()) {
           int nextc = c + acquires;
           if (nextc < 0) // overflow
               throw new Error("Maximum lock count exceeded");
           setState(nextc);
           return true;
       }
       // 由于上面判断都无法成功所以直接返回false
       return false;
   }
  1. 由于 step_4 执行完以后返回为 false 再次来到 step_3 进入下一个方法的逻辑

    public final void acquire(int arg) {
        if (!tryAcquire(arg) && // tryAcquire(arg); 返回为false 取反 为 true
            // 由于括号的优先级最高所以先进入括号内的 addWaiter(Node.EXCLUSIVE) 方法
            // 点进源码可知  Node.EXCLUSIVE 默认值为null 所以传递进去的也为null
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

  2. 来到 addWaiter(Node.EXCLUSIVE) 方法

    private Node addWaiter(Node mode) {  // 当前 mode 的值为 null
        // 将当前线程包装成一个 Node 节点 
        Node node = new Node(Thread.currentThread(), mode);
        // Try the fast path of enq; backup to full enq on failure
        Node pred = tail; // aqs有头尾指针默认为null 将tail 赋值给 pred
        if (pred != null) {  // 此判断无法进入 所以直接进入到 方法 enq(node)
            node.prev = pred;
            if (compareAndSetTail(pred, node)) {
                pred.next = node;
                return node;
            }
        }
        enq(node); // 来到这个方法 下图的 线程B 即为 node 
        return node;  
    }

     

  1. 来到 enq node 的值即为上图的线程B

   private Node enq(final Node node) { // node 的值为 上图的线程B 然后进入cas
       for (;;) {
           Node t = tail;  // ①一个新的节点 也指向 null 
                           // ②当前t为新创建的哨兵节点不为null,直接进入else
           if (t == null) { // Must initialize  // ①当前的 t 为null 所以可以进入
               // ①创建出一个新的节点但是没有内容,并设置为头节点 如下图
               if (compareAndSetHead(new Node())) 
                   tail = head;  // ①将tail 也指向新创建的节点
           } else {
               // 最终效果如下第二张图
               // 第二次循环直接来到else
               // 将 线程B的前驱节点指向t也就是哨兵节点
               node.prev = t;
               // 比较并交换尾节点 当前的尾节点为 t 所以此处为true
               if (compareAndSetTail(t, node)) {
                   // 将 哨兵节点的下一个指向线程B
                   t.next = node;
                   return t;
               }
           }
       }
   }

 

 

  1. 回到 step_5

    public final void acquire(int arg) {
        if (!tryAcquire(arg) && // tryAcquire(arg); 返回为false 取反 为 true
            // 由于括号的优先级最高所以先进入括号内的 addWaiter(Node.EXCLUSIVE) 方法
            // 点进源码可知  Node.EXCLUSIVE 默认值为null 所以传递进去的也为null
            
            // addWaiter(Node.EXCLUSIVE) 方法最终返回Node包装的线程B
            // 然后进入到 acquireQueued 方法
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

  2. 来到 acquireQueued() 方法

    // node为线程B , arg 为 1
    final boolean acquireQueued(final Node node, int arg) {
        boolean failed = true;
        try {
            boolean interrupted = false;
            for (;;) {
                // 点进 predecessor 可知
                // p的值为 当前线程B节点的前一个节点 也就是 哨兵节点
                
                // 第二次循环
                // p还是哨兵节点
                final Node p = node.predecessor();
                // p为哨兵节点head也为哨兵节点 所以第一个判断为true
                // 第二个判断arg让B线程再次抢夺一下 最终为 false
                // 所以进入到 下一个if
                
                // 第二次循环跟第一次一样还是无法进入直接来到第二个if
                if (p == head && tryAcquire(arg)) {
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return interrupted;
                }
                // 来到这个判断进入到 step_10
                // p 为哨兵节点 node 为线程B
                // 第一个为false 所以直接退出第一次循环
                
                // 第二次循环 再次来到 step_10
                // 第一个判断为true 
                if (shouldParkAfterFailedAcquire(p, node) &&
                    // 此方法来到step_11 可知 将当前线程B被挂起
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

  3. shouldParkAfterFailedAcquire()

    // pred为哨兵节点  node 为线程B
    private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
        // 第一次来到此方法ws为哨兵节点的waitStatus 为 0
        // 第二次来到此方法ws为哨兵节点的waitStatus 为 -1
        int ws = pred.waitStatus; 
        // 下面的判断都不满足 直接进入到else
        
        // 第二次进入此方法
        // 满足条件返回true 回到step_9
        if (ws == Node.SIGNAL) // SIGNAL 为 -1 
            /*
             * This node has already set status asking a release
             * to signal it, so it can safely park.
             */
            return true;
        if (ws > 0) {
            /*
             * 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.
             */
            
            // 比较并赋值 将 哨兵节点的 waitStatus 设置为 -1 最终返回false
            compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
        }
        return false;
    }

 

  1. parkAndCheckInterrupt()

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

第二个线程完毕 接下来是第三个线程

  1. 来到非公平的lock锁 依然是进入到 acquire(1);

    final void lock() {
        if (compareAndSetState(0, 1))
            setExclusiveOwnerThread(Thread.currentThread());
        else
            acquire(1); // step_2
    }

  2. acquire()

    // arg 的值为 1
    public final void acquire(int arg) {
        if (!tryAcquire(arg) && // 依然是无法获取到资源 返回false 取反 为true 
            // acquireQueued step_4    addWaiter() step_3 返回一个线程C的node节点
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

  3. addWaiter()

    // 当前mode 为线程C
    private Node addWaiter(Node mode) {
        // 将线程C封装成一个Node
        Node node = new Node(Thread.currentThread(), mode);
        // Try the fast path of enq; backup to full enq on failure
        Node pred = tail;  // 当前tail为 线程B 所以 prev 也为 线程B
        if (pred != null) {// 满足判断进入逻辑
            node.prev = pred; // 将线程C的前驱节点指向 线程B
            if (compareAndSetTail(pred, node)) { // 比较并设置尾巴节点将尾巴节点指向线程C
                pred.next = node; // 将线程B的next指向线程C
                return node;   // 直接返回node
            }
        }
        enq(node);  // step_4
        return node;
    }

 

  1. acquireQueued()

// node 的值为 线程C , arg 的值为 1
final boolean acquireQueued(final Node node, int arg) {
    boolean failed = true;
    try {
        boolean interrupted = false;
        for (;;) {
            // p 的值为 线程C的前一个节点 B 节点
            final Node p = node.predecessor(); 
            // p != head 来到第二个if
            if (p == head && tryAcquire(arg)) {
                setHead(node);
                p.next = null; // help GC
                failed = false;
                return interrupted;
            }
            // 第一个条件见 step_5
            if (shouldParkAfterFailedAcquire(p, node) &&
                // 将线程C挂起
                parkAndCheckInterrupt())
                interrupted = true;
        }
    } finally {
        if (failed)
            cancelAcquire(node);
    }
}
  1. // pred 为 线程线程B , node为线程C
    private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
        int ws = pred.waitStatus; // ws = 0
        // 直接来到else
        if (ws == Node.SIGNAL) // SIGNAL的值为-1不满足
            /*
             * This node has already set status asking a release
             * to signal it, so it can safely park.
             */
            return true;
        if (ws > 0) {
            /*
             * 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.
             */
            // 将线程B的waitStatus 的值设置为 -1 
            compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
        }
        return false;
    }

 

到此我们的入队就完成了,接下来是出队,下图为入队后的图例

 

  1. 来到unlock() 的方法进入到 sync.release(1); 方法

    // arg 的值为 1
    public final boolean release(int arg) {
        // 尝试释放 tryRelease 方法 看 step_2
        // 返回为true 进入判断
        if (tryRelease(arg)) {
            // h = 哨兵节点
            Node h = head;
            // 第一个满足 && 第二个满足
            if (h != null && h.waitStatus != 0)
                // unparkSuccessor(h) 方法看 step_3
                unparkSuccessor(h);
            return true;
        }
        return false;
    }

  1. tryRelease(int releases);

    // releases 的值为 1
    protected final boolean tryRelease(int releases) {
        // 当前的 state 为 1 所以 c的值为 0
        int c = getState() - releases;
        if (Thread.currentThread() != getExclusiveOwnerThread())
            throw new IllegalMonitorStateException();
        // 默认为 false 
        boolean free = false;
        // 满足条件
        if (c == 0) {
            free = true;
            // 将当前持有资源的线程设置为(也就是当前的线程A) null
            setExclusiveOwnerThread(null);
        }
        // 将state设置为0
        setState(c);
        // return true;
        return free;
    }

  1. unparkSuccessor(h);

    // node 为 哨兵节点
    private void unparkSuccessor(Node node) {
        /*
         * If status is negative (i.e., possibly needing signal) try
         * to clear in anticipation of signalling.  It is OK if this
         * fails or if status is changed by waiting thread.
         */
        // ws 的值为 -1
        int ws = node.waitStatus;
        // 满足条件
        if (ws < 0)
            // 比较并设置等待状态 设置为 0
            compareAndSetWaitStatus(node, ws, 0);
    ​
        /*
         * Thread to unpark is held in successor, which is normally
         * just the next node.  But if cancelled or apparently null,
         * traverse backwards from tail to find the actual
         * non-cancelled successor.
         */
        // s = 线程B
        Node s = node.next;
        // 第一个不满足 || 第二个不满足; 来到第二个if
        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;
        }
        // 线程B != null 
        if (s != null)
            // 将线程B唤醒
            LockSupport.unpark(s.thread);
    }

 

执行完上述以后 会再次来到下面的方法

// node为当前线程B
final boolean acquireQueued(final Node node, int arg) {
    boolean failed = true;
    try {
        boolean interrupted = false;
        for (;;) {
            // p为B的前驱节点为 哨兵节点
            final Node p = node.predecessor();
            // 第一个满足 && 因为当前的state已经设置为0所以获取成功 ; 进入if
            if (p == head && tryAcquire(arg)) {
                // 设置头节点为线程B
                // setHead(node) 见 step_B
                setHead(node);
                // 哨兵节点的next指向null
                p.next = null; // help GC
                failed = false;
                
                // 至此 线程B抢占资源 原来的线程B成为新的哨兵节点
                return interrupted;
            }
            
            
            if (shouldParkAfterFailedAcquire(p, node) &&
                // 来到这里以后首先会来到这里 查看step_A
                // 这里为false 直接进行第二次循环
                parkAndCheckInterrupt())
                interrupted = true;
        }
    } finally {
        if (failed)
            cancelAcquire(node);
    }
}

 

A. parkAndCheckInterrupt()

private final boolean parkAndCheckInterrupt() {
    LockSupport.park(this);
    // 因为当前B线程已经被唤醒了 所以返回false , 打断状态为 false
    return Thread.interrupted();
}

B.setHead(Node node)

// node 为 线程B
private void setHead(Node node) {
    // 头节点指向线程B
    head = node;
    // 将当前的线程B设置为null
    node.thread = null;
    // 线程B的prev指向null
    node.prev = null;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值