`
spring5365
  • 浏览: 71459 次
  • 性别: Icon_minigender_1
  • 来自: 钓鱼岛
社区版块
存档分类
最新评论

AbstractQueuedSynchronizer

阅读更多
/**
 将结点插入队列,如果队列为空,初始化队列,否则将结点入队列
 **/
private Node enq(final Node node) {
    for (;;) {
        Node t = tail;
        if (t == null) { // 尾结点为null时初始化
            Node h = new Node();
            h.next = node;
            node.prev = h;
            if (compareAndSetHead(h)) { //1比较并更新头结点
                tail = node; //如果这一行CPU切换了线程,其它线程同样执行插入节点操作时,会在1处执行失败,
                return h;    //直到第一次执行插入节点操作的线程恢复运行时尾结点才会更新成功
            }
        }
        else {
            node.prev = t;  //如果队列不为空,让新结点的前一节点指向尾结点
            if (compareAndSetTail(t, node)) { 
                t.next = node; 
                return t;
            }
        }
    }
}

/**
 创建和入队节点给定线程和模式
 **/
private Node addWaiter(Node mode) {
    Node node = new Node(Thread.currentThread(), mode);
    // 尝试将新结点插入队列,失败则进入enq函数(循环尝试)
    Node pred = tail;
    if (pred != null) {
        node.prev = pred;
        if (compareAndSetTail(pred, node)) {
            pred.next = node;
            return node;
        }
    }
    enq(node);
    return node;
}

/**
 唤醒给定结点的继任节点
 **/
private void unparkSuccessor(Node node) {
    //修改结点的waitStatus状态,成功失败都OK,失败说明有线程已修改完状态
    //成功也说明节目的状态已被修改
    compareAndSetWaitStatus(node, Node.SIGNAL, 0);
 
    //继任结点是null or 继任结点被取消时,从队尾寻找真实继任结点
    Node s = node.next;
    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;
    }
    if (s != null)
        LockSupport.unpark(s.thread);
}
    
    /**
     未理解此方法
     **/
    private void setHeadAndPropagate(Node node, int propagate) {
        setHead(node);
        if (propagate > 0 && node.waitStatus != 0) {
            Node s = node.next;
            if (s == null || s.isShared())
                unparkSuccessor(node);
        }
    }

/**
 检查并更新获取失败节点的状态
 **/
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
    int s = pred.waitStatus;
    if (s < 0)
        //表明此节点的继任节点需求释放,可以安全park
        return true;
    if (s > 0) {
        //表明前任节点被取消,继续向前循环
        do {
            node.prev = pred = pred.prev;
        } while (pred.waitStatus > 0);
        pred.next = node;
    } else
        //表明需要一个signal,但不能park,调用者进行循环重试,确保park以前不能获取锁
        compareAndSetWaitStatus(pred, 0, Node.SIGNAL);
    return false;
}


// Condition内部类
/**
  检查中断,如果被唤醒之前中断抛异常,如果唤醒之后中断重新中断,否则返回0
 **/
private int checkInterruptWhileWaiting(Node node) {
        return (Thread.interrupted()) ?
            ((transferAfterCancelledWait(node))? THROW_IE : REINTERRUPT) :
            0;
    }

    /**
     如果一个结点最初被放置在等待队列,现在在同步队列等待重新获取锁,返回true。
     **/
    final boolean isOnSyncQueue(Node node) {
        //条件队列初始化时,prev节点为空,此条件说明此节点还在条件队列
        if (node.waitStatus == Node.CONDITION || node.prev == null)
            return false;
        if (node.next != null) // If has successor, it must be on queue
            return true;
        return findNodeFromTail(node);
    }

        public final void await() throws InterruptedException {
            if (Thread.interrupted())
                throw new InterruptedException();
            //添加条件结点
            Node node = addConditionWaiter();
            //释放独占锁
            int savedState = fullyRelease(node);
            int interruptMode = 0;
            //节点扔在等待队列自旋
            while (!isOnSyncQueue(node)) {
                LockSupport.park(this);
                //检查中断,等待时被中断,跳出循环
                if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                    break;
            }
            //重新获取节点并检查中断
            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                interruptMode = REINTERRUPT;
            //解除取消的等待节点
            if (node.nextWaiter != null)
                unlinkCancelledWaiters();
            //处理中断
            if (interruptMode != 0)
                reportInterruptAfterWait(interruptMode);
        }

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics