zoukankan      html  css  js  c++  java
  • AQS源码的一点思考

    /**
         * Acquires in exclusive uninterruptible mode for thread already in
         * queue. Used by condition wait methods as well as acquire.
         *
         * @param node the node
         * @param arg the acquire argument
         * @return {@code true} if interrupted while waiting
         */
        final boolean acquireQueued(final Node node, int arg) {
            boolean failed = true;
            try {
                boolean interrupted = false;
                // 这里是一个自旋操作,用来进行获取锁或者进入阻塞的动作
                for (;;) {
                    final Node p = node.predecessor();
                    // 如果前驱节点为头节点(head,其实是一个虚节点,不关联任何线程),
                    // 并且尝试加锁(tryAcquire)成功的话,讲当前节点设置为头节点(head)
                    if (p == head && tryAcquire(arg)) {
                        setHead(node);
                        p.next = null; // help GC
                        failed = false;
                        return interrupted;
                    }
                    // 如果当前节点的前驱节点不是头节点,或者是头节点但是没有抢到锁(被非公平锁抢占了)
                    // 就会通过shouldParkAfterFailedAcquire判断当前节点是否需要将自己挂起,进入阻塞状态
                    if (shouldParkAfterFailedAcquire(p, node) &&
                        parkAndCheckInterrupt())
                        interrupted = true;
                }
            } finally {
                if (failed)
                    cancelAcquire(node);
            }
        }
    
    /**
         * Checks and updates status for a node that failed to acquire.
         * Returns true if thread should block. This is the main signal
         * control in all acquire loops.  Requires that pred == node.prev.
         *
         * @param pred node's predecessor holding status
         * @param node the node
         * @return {@code true} if thread should block
         */
        private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
            int ws = pred.waitStatus;
            // 如果当前节点的前驱节点的waitStatus为Node.SIGNAL的话,
            // 就意味着当前节点需要进入阻塞状态,将自己挂起
            if (ws == Node.SIGNAL)
                /*
                 * 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.
                 */
                // 如果当前节点的前驱节点的waitStatus>0的话,意味着前驱节点的waitStatus=CANCELLED,
                // 那么就要从前往后遍历,将CALCELLED的前驱节点都从链表中摘除
                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不是CANCELLED(1),也不是SIGNAL(-1),
                // 那就将当前节点的前驱节点的waitStatus设置为SIGNAL(意思就是当前节点需要进入阻塞状态,
                // 当然这里只是先将当前节点的前驱节点的waitStatus设置为SIGNAL,
                // 下一轮自旋才能将当前节点设置为阻塞状态)
                compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
            }
            return false;
        }
    
  • 相关阅读:
    css文本及文本装饰
    css尺寸常用样式
    了解css的两大特性
    css长度单位及字体
    css颜色
    css选择器详解
    了解css
    html行级元素与块级元素以及meta标签的使用
    了解html表单
    html图片和html实体
  • 原文地址:https://www.cnblogs.com/rocker-pg/p/12510949.html
Copyright © 2011-2022 走看看