Java中用信号量获取、释放、再获取多个permit时是否有死锁?

Is there a deadlock when acquiring, releasing, and then acquiring multiple permits with semaphores in Java?

以下代码片段是 https://leetcode.com/problems/print-in-order/ 的解决方案,它使用单个信号量按顺序运行 printFirst.run()printSecond.run()printThird.run()。三个线程 A、B 和 C 调用函数。线程 A 将调用 first,线程 B 将调用 second,线程 C 将调用 third.

我理解为什么 third 中需要 lock.acquire(); 后跟 lock.release();,而不是立即调用 lock.acquire(2);,因为 Java 分配许可的方式到队列中的等待线程。调用 lock.acquire(2); 会造成死锁,因为没有任何东西可以释放足够的许可。

话虽这么说,但我不明白 lock.acquire(); 后面跟着 lock.release(); 是如何修复它的。

有人可以向我解释在 first 首先调用 lock.release() 然后 thirdsecond 之前调用 lock.acquire(); lock.release(); lock.acquire(2); 的情况下会发生什么吗运行?这是否会导致死锁,就像调用 lock.acquire(2); 本身会导致死锁一样?这只是一种不太可能的情况,这就是它起作用的原因吗?

如有任何帮助,我们将不胜感激,谢谢!

class Foo {
    
    private Semaphore lock = new Semaphore(0);

    public void first(Runnable printFirst) throws InterruptedException {
        // printFirst.run() outputs "first". Do not change or remove this line.
        printFirst.run();
        lock.release();
    }

    public void second(Runnable printSecond) throws InterruptedException {
        lock.acquire();
        // printSecond.run() outputs "second". Do not change or remove this line.
        printSecond.run();
        lock.release(2);
    }

    public void third(Runnable printThird) throws InterruptedException {
        lock.acquire();
        lock.release();
        lock.acquire(2);
        // printThird.run() outputs "third". Do not change or remove this line.
        printThird.run();
    }
}

我现在明白为什么这是正确的并且不会死锁了。

third()中的acquire(2)之前有acquire()release()意味着许可证的数量在获得时保证为1,这意味着second() 可以获取并且仍在进行中,或者 second() 已经调用了 acquire() 并且有 0 个许可,但这并不重要,因为 second() 即将 release(2),这将允许 third() 继续。

third() 中没有 acquire()release(),有可能 third()acquire(2) 在其他线程中取得任何进展之前(即没有许可并且 second() 没有成功获得),这意味着 first() 中释放的许可将走向 third() 而第二个获得永远不会成功。