【问题标题】:How to acquire semaphore in order to notify waiting threads on that semaphore? (Java)如何获取信号量以通知该信号量上的等待线程? (爪哇)
【发布时间】:2013-06-02 18:38:11
【问题描述】:

有多个消费者线程在一个信号量上等待异步到达的数据,这些数据由单个生产者线程提供。如果消费者已经获取了信号量,生产者如何获取信号量通知他们?在这里,它被阻塞了,不能做一个 notifyAll()

 Object receiveSemaphore = new Object();

// consumer threads
synchronized (receiveSemaphore) {
    while (!dataIsReady) {
        try {
            receiveSemaphore.wait();
        } catch (InterruptedException e) {
        }
    }
}

// producer thread          
synchronized (receiveSemaphore) {
    dataIsReady = true;
    receiveSemaphore.notifyAll();
}

当然,删除“同步”会导致

java.lang.IllegalMonitorStateException
    at java.lang.Object.notifyAll(Native Method)

再次,生产者线程被阻塞,无法获取信号量来通知消费者。

更新:我应该提到第二次数据准备好时失败。第一次数据准备好时,生产者没有阻塞。下次生产数据时,生产者被阻止。此外,代码中有两个地方生产者执行 notifyAll(),但我在这里仅将其显示为一个地方。

更新 2: 不幸的是,我无法将程序简化为 SSCCE,因为我不明白问题到底出在哪里 - 此外,这些实际上是 JavaFX 服务,而不是普通线程.

我将所有不相关的代码移出同步块。 我使用 jstack 来获取线程转储和 TDA 来查看它。 它报告有 2 个监视器(在其他不相关的监视器中)。 其中一个是包含数据的 StringBuffer,另一个是类本身。 但是它没有报告任何等待线程。 我已经使类的一种方法同步,现在我删除了关键字。 线程争用似乎已经消失。

顺便说一下,receiveSemaphore 只是一个 Object - 一个通用信号量,而不是 java.util.Semaphore 类。

【问题讨论】:

  • 让您的生活更轻松,使用Semaphore 类。实际上,请使用完整的 java.util.concurrent 包。
  • 阅读wait() 方法的javadoc(提示,它回答了你的问题)。另外,不要在这里使用“信号量”这个词,因为它与您正在做的事情不同。
  • @likejiujitsu 只需使用BlockingQueue;它是标准的、简单的、经过验证的结构。当你在网上搜索时,例子比比皆是。
  • 如果你对你的进程进行线程转储,你应该能够看到哪个线程拥有监视器。
  • @likejiujitsu 然后在SSCCE 中重现该错误;但是对于您需要开始工作的代码,请使用BlockingQueue。你将不得不习惯它而不是Semaphore

标签: java multithreading


【解决方案1】:

不幸的是,我无法将程序简化为 SSCCE,因为我不明白问题出在哪里 - 此外,这些实际上是 JavaFX 服务,而不是普通线程。

我将所有不相关的代码移出同步块。我使用 jstack 来获取线程转储和 TDA 来查看它。它报告有 2 个监视器(在其他不相关的监视器中)。其中一个是包含数据的 StringBuffer,另一个是类本身。但是它没有报告任何等待线程。我已经使类的一种方法同步,现在我删除了关键字。线程争用似乎已经消失。

顺便说一下,receiveSemaphore 只是一个 Object - 一个通用信号量,而不是 java.util.Semaphore 类。

【讨论】:

  • receiveSemaphore 不是信号量而是监视器。简而言之,一个信号量有一个值和两个方法,“up”和“down”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-21
  • 1970-01-01
  • 1970-01-01
  • 2014-10-21
  • 2012-02-03
  • 2013-10-20
相关资源
最近更新 更多