有一些消费者线程在信号量上等待由异步到达的数据,由单个生产者线程提供。如果消费者已经抓住它,生产者如何获得信号量通知他们?在这里,它被阻止,无法执行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();
}
当然,删除'synchronized'会导致
java.lang.IllegalMonitorStateException
at java.lang.Object.notifyAll(Native Method)
同样,生产者线程被阻止,无法获取信号量以通知消费者。
更新:我应该提一下,第二次数据就绪时会失败。第一次数据准备就绪,生产者没有阻止。下一次生成数据时,生产者被阻止了。在代码中有两个地方,生产者在那里做一个notifyAll(),但我在这里只显示一个地方。
更新2:不幸的是,我无法将程序缩减到SSCCE,因为我不明白问题究竟在哪里 - 而且,这些实际上是JavaFX服务,而不是普通线程。
我将所有不相关的代码移出synchronized块。 我使用jstack获取线程转储和TDA来查看它。 它报告说有2个监视器(其他不相关的监视器)。 其中一个是包含数据的StringBuffer,另一个是类本身。 但它没有报告任何等待线程。 我已经使类的一个方法同步,现在我删除了关键字。 线程争用似乎已经消失。
顺便说一句,receiveSemaphore只是一个Object - 一个通用的信号量,而不是类java.util.Semaphore。
答案 0 :(得分:1)
不幸的是,我无法将程序缩减为SSCCE,因为我不明白问题究竟在哪里 - 而且,这些实际上是JavaFX服务,而不是普通的线程。
我将所有不相关的代码移出synchronized块。我使用jstack获取线程转储和TDA来查看它。它报告说有2个监视器(其他不相关的监视器)。其中一个是包含数据的StringBuffer,另一个是类本身。但它没有报告任何等待线程。我已经使类的一个方法同步,现在我删除了关键字。线程争用似乎已经消失。
顺便说一句,receiveSemaphore只是一个Object - 一个通用的信号量,而不是类java.util.Semaphore。