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

为什么信号量起作用而ReentrantLock不起作用?

勾炳
2023-03-14

我正在从LeetCode中尝试一个简单的并发问题。我在大学里非常简短地研究过这个主题,但没有使用Java API。我似乎无法使用reentrantlock(或据我所知的任何其他lock)来解决这个问题,而不会遇到IllegalMonitorStateException。然而,信号量(这似乎有些矫枉过正,因为我只需要使用二进制值)似乎工作得很好。这是为什么?

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class Foo {

    private Lock printedFirst;
    private Lock printedSecond;

    public Foo() {
        this.printedFirst = new ReentrantLock();
        this.printedSecond = new ReentrantLock();
        printedFirst.lock();
        printedSecond.lock();
    }

    public void first(Runnable printFirst) throws InterruptedException {
        printFirst.run();
        printedFirst.unlock();
    }

    public void second(Runnable printSecond) throws InterruptedException {
        printedFirst.lock();
        try {
            printSecond.run();
        } finally {
            printedSecond.unlock();
        }

    }

    public void third(Runnable printThird) throws InterruptedException {
        printedSecond.lock();
        try {
            printThird.run();
        } finally {}
    }
}

使用信号量按预期工作的代码:

import java.util.concurrent.Semaphore;

class Foo {

    private Semaphore printedFirst;
    private Semaphore printedSecond;

    public Foo() {
        this.printedFirst = new Semaphore(0);
        this.printedSecond = new Semaphore(0);
    }

    public void first(Runnable printFirst) throws InterruptedException {
        printFirst.run();
        printedFirst.release();
    }

    public void second(Runnable printSecond) throws InterruptedException {
        printedFirst.acquire();
        try {
            printSecond.run();
        } finally {
            printedSecond.release();
        }

    }

    public void third(Runnable printThird) throws InterruptedException {
        printedSecond.acquire();
        try {
            printThird.run();
        } finally {}
    }
}

共有1个答案

索瀚海
2023-03-14

同步有两个主要用例:资源访问和事件传递。您试图解决的并发问题需要事件传递:第二个线程等待来自第一个线程的信号,第三个线程等待来自第二个线程的信号。信号,我的意思是,是空的事件,它们携带一个事件已经发生的事实,没有任何额外的细节。

信号量非常适合信号传递(尽管也可用于资源访问)。reentrantlock是为资源访问而设计的。从技术上讲,任何事件传递机制都建立在资源访问的基础上。因此,您可以使用reentrantlocks进行信号传递,但它需要一些额外的编程(在@billie的回答中演示)。

 类似资料:
  • 所以我有了这个网格: 在中有一个没有空格的超长字符串。是具有固定尺寸的占位符。这就产生了上述结果: 但将更改为会得到以下结果: 它会溢出其父级和屏幕大小。为什么它的行为不像Minmax? 码本

  • 通过选择,,和,我创建了一个全新的Spring初始化项目。 我做了一个小项目: 我试着将三个人保存到数据库中。保存方法只返回需要执行的Mono。如果我尝试通过简单的订阅来执行它,一切都很好: 但是,当我使用而不是时,应用程序挂起: 如果我手动查询数据库,我会看到Jim已被保存,但Jack和John未被保存。 这是窃听器,还是我做错了什么?我希望在代码进一步发展之前保证用户在数据库中,所以我真的很想

  • 拿我正在试验的这个非常简单的框架来说(这样我就可以更深入地学习JavaScript的函数原型。) 这工作很棒。控制台的输出是: 对象{ui:对象,操作:"单击设置openSidebar",函数:对象,运行:函数} 但是,当我尝试这样做时: 在openSidebar()中的的上下文是openSidebar(又名bind没有效果)。控制台输出: 对象{openSidebar:function} 但是,

  • 问题内容: 我正在尝试从JSON网址获取集合。骨干网确实发送了请求并得到了响应,但是在它之后的集合中没有: 这是我的JavaScript: 响应中的JSON 响应中的Content-Type HTTP标头为。 为什么不将其加载到集合中?JSON是否正确? 一些更多的代码: 问题答案: 是异步的。尝试 要么 要么

  • 问题内容: 我有三部分字符串,每个部分用 符号分隔 。例如, 现在,当我使用这样的方法拆分它时: 它包含整个字符串作为单个元素的数组。 但是当我使用这个: 它完美的作品是什么,我想这意味着 现在的数组包含,并分别对指数0,1和2。 我想知道为什么第一次使用时不起作用,因为我在使用 问题答案: 因为字符是在正则表达式中用来标记行尾的保留令牌。因此,您必须使用进行 转义。

  • 问题内容: 我现在有点困惑。我尝试过: 并得到: 但是,我想要: 我的代码有什么问题? 问题答案: 您没有将其分配给。字符串是 不可变的 。 您需要将其分配回。

  • 问题内容: 我正在尝试这样做: 第一行有效: 但是接下来的两个: 和 只是输出 为什么? 问题答案: 因为你需要加入同,只是列出了内容直接,内容不具有完整路径。 范例- 如果未提供完整路径,则在当前目录中搜索,因此当您给出时,将获得正确的列表。 范例- 假设某个文件夹-具有文件-并在其中。 当您执行-时,返回的列表类似于- 即使您在其中提供绝对路径,列表中返回的文件也将具有指向目录的相对路径。您将

  • 我想知道两次当地约会之间的时间。我使用了下面的代码: 我有以下错误: