当前位置: 首页 > 知识库问答 >
问题:

在Java中,使用信号量获取、释放然后获取多个许可证时是否存在死锁?

章海
2023-03-14

以下代码段是https://leetcode.com/problems/print-in-order/它首先运行打印。run(),打印秒。运行(),然后打印第三个。使用单个信号量按顺序运行()。三个线程A、B和C调用这些函数。线程A将调用第一个,线程B将调用第二个,线程C将调用第三个。

我理解为什么锁。获取() 后接锁定。释放() 中需要code>,而不是调用锁。获取(2) 立即。正在调用锁定。获取(2) 创建死锁,因为任何东西都无法释放足够的许可。

话虽如此,我不明白lock.acquire();后跟lock.release();在此之前如何修复它。

有人能给我解释一下在第一个首先调用lock.release()然后第三个调用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();
    }
}

共有1个答案

季俭
2023-03-14

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

在第三个()中的第二个()中,在第二个()之前有一个()和一个()释放,这意味着许可证的数量保证为1,这意味着第二个()可以获取并继续进行,或者第二个()已经调用了,并且有0个许可证,但这并不重要,因为第二个()将要发布(2),这将允许第三个()继续。

如果第三()中没有获取()释放(),则第三()获取(2)在其他线程中取得任何进展之前(即没有许可证并且第二()尚未成功获取),这意味着first()中释放的许可证将走向第三(),而第二的获取将永远不会成功。

 类似资料:
  • 我正在考虑一个语句的示例“在一个线程中获取许可证,然后从另一个线程中释放”。 我对信号量的理解是,它维护一组许可。Thread应在通过临界截面之前获得许可证,然后许可证递减1。一旦Thread完成临界截面,它将释放许可证,许可证将增加1<示例: 1。ATM机,配备一名保安,根据机器的可用性允许人们使用。机器越多,许可证就越多。一位客户购买了一台ATM机,完成后将其释放 2。银行的柜台,如果柜台空闲

  • 问题内容: 我正在做与此问题类似的事情,在此我有一个复选框列表作为自定义编辑控件。区别在于我想从服务器获取列表(不是在客户端使用 Check1,Check2,Check3进行 硬编码)。 在列设置或 custom_element 函数中,有什么方法可以这样做吗? 似乎我需要与用于选择项的 dataUrl 属性类似的 东西 ,但这似乎仅适用于选择项(不适用于自定义项)。 有什么建议? 问题答案: 您

  • 问题内容: 如果我有这样的方法: 如何同时获取@LinkLength和@LinkRange批注? 问题答案: 我假设您想反射地访问这些注释。这是一个例子: 输出以下内容: 以下是使用的方法: 只会得到一个公共方法。要获取非公开方法,请参见。 从延伸。 ,和和(和其他类型)全部继承。 上面的示例充分利用了有关该方法的知识。换句话说,我知道有一个参数,知道会返回,而且我知道参数化类型有一个类型实参。反

  • 问题内容: 有什么好的方法可以在运行时将剩余的内存提供给JVM?这种情况的用例是使Web服务在接近内存限制时通过拒绝一个新的错误消息“太多的人使用此,请稍后再试”,而不是因OutOfMemory错误而突然死亡而接近失败,从而正常失败。 注意,这与事先计算/估算每个对象的成本无关。原则上,我可以根据该估算值估算对象占用并拒绝新连接的内存量,但这似乎有点hacky /脆弱。 问题答案: 这是该主题给出

  • 接口说明 获取该机器硬件绑定的唯一许可码 如需调用,请访问 开发者文档 来查看详细的接口使用说明 该接口仅开放给已获取SDK的开发者 API地址 POST /api/license/1.0.0/code 是否需要登录 否 请求字段说明 无 响应字段说明 参数 类型 说明 licenseCode String 许可码 响应成功示例 { "code": 200, "data": { "

  • 我有一些线程,它们被赋予随机数(1到n),并被指示按排序顺序打印它们。我使用了信号量,这样我就获得了许可数=随机数,并释放了一个比所获得的多的许可。 获得=随机数;释放=1个随机数 信号量的初始许可计数为1。所以随机数为1的线程应该获得许可,然后是2,依此类推。 这是根据下面给出的文档支持的 不要求释放许可证的线程必须通过调用acquire()获得该许可证。 问题是我的程序在1代表n后卡住了 我的