V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
SachinBeyond
V2EX  ›  问与答

Java 并发包 AQS 实现 中 acquireQueued 源码理解的问题

  •  
  •   SachinBeyond · 2020-09-04 19:14:19 +08:00 · 591 次点击
    这是一个创建于 1552 天前的主题,其中的信息可能已经有所发展或是发生改变。

    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); } }

    我们知道 AQS 有一个等待队列存放 因获取不到锁而阻塞的线程节点。
    从上面的 实现中我们也看到  当锁被释放的时候  唤醒下一个节点线程的规则是  获取 head 节点的 next 节点作为下一个要被唤醒的节点,然后让这个节点尝试获取锁,也就是    if (p == head && tryAcquire(arg))  。 判断当前节点的前屈是否是 head,如果是就尝试获取锁。当 if 执行成功的时候就会退出 for 循环
    
    问题: ( 1 ) for 死循环仅有一种退出方式(上面提到的  )吗?
     ( 2 )我们不是说 ReentrantLock 等待可中断吗? 但是从 for 死循环中 我们看到即使你 中断了 也退出不 for 循环吧?
    
    1 条回复    2020-09-04 19:15:16 +08:00
    SachinBeyond
        1
    SachinBeyond  
    OP
       2020-09-04 19:15:16 +08:00
    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);
    }
    }
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   6014 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 02:05 · PVG 10:05 · LAX 18:05 · JFK 21:05
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.