【问题标题】:Thread condition never wakes线程条件永远不会唤醒
【发布时间】:2017-05-08 09:26:49
【问题描述】:

我有一个线程,当它运行时,它会创建一个 Message 对象,该对象被放入监视器的链表中。同时,另外两个线程等待这个列表获取一个Message对象在里面,一会儿(linkedlist.isEmpty()) canGetMessage.await();循环,但即使我正在发送 canGetMessage.signalAll();命令将对象放入列表时,其他两个线程永远不会唤醒。

public void deliverMessage(Message m){
lock.lock();

try{
  linkedlist.add(m);
  canGetMessage.signalAll();
 }finally{
  lock.unlock();
 }
}


public Message getMessage(){
lock.lock();

try{
 while(linkedlist.isEmpty()){
  canGetMessage.await();
  }
 return linkedlist.remove(); //returns the item that has been in the list the longest
 }
catch (InterruptedException e) { } //not required to handle these

finally{
 lock.unlock();
}

我有 println 来查看它何时退出 while 循环,但这从未发生过,我不知道为什么......

编辑:只是为了说明,我使用的锁是 ReentrantLock

【问题讨论】:

  • 为什么不使用 BlockingQueue 和生产者-消费者模式?
  • 发布一个完整的最小示例来重现问题。
  • locklinkedlistcanGetMessage有哪些类型,它们是如何创建的?而且,是的,MCVE 会非常有用。

标签: java multithreading


【解决方案1】:

猜测;您在这里遇到问题:

lock.lock();

如果发送方/接收方使用相同锁定对象,这将不起作用。接收者获取锁;并且在发件人向列表中添加新条目之前不会释放它。

但发件人无法到达该部分;因为发件人试图锁定已经锁定的锁。所以锁定的锁会阻塞。

“正确”的答案是使用BlockingQueue 连接发送方/接收方 - 而不是重新发明“像队列”这样的东西。有关如何使用 BlockingQueue 的更多材料,请参阅here

【讨论】:

  • 不,canGetMessage.await() 释放锁(假设条件已从该锁创建)。
  • 可能......让我们看看 OP 怎么说。如果对他没有帮助,我不介意删除答案。
  • @Telanore 你不应该使用单独的锁。如果您需要解释,请发布一个完整的最小示例来重现该问题。或者继续使用 BlockingQueue(我同意,这是一个更好的解决方案)。
【解决方案2】:

我向大家道歉,事实证明问题在于线程本身的创建,我无意中为每个线程制作了单独的监视器,而不是它们都使用相同的监视器......

【讨论】:

  • 你要么想改进问题和自我回答......要么可能删除你的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多