【问题标题】:In Java, why does a thread have to compete for resources after waking up from .wait()?在 Java 中,为什么线程从 .wait() 唤醒后必须竞争资源?
【发布时间】:2019-04-10 07:09:19
【问题描述】:

例如在这个经典的消费者-生产者代码 sn-p 中:

synchronized (this) {
  while (queue.isEmpty()) {
    this.wait();
  }
  queue.remove();
  this.notifyAll();
}

生产者通知的.wait()消费者线程将被唤醒,然后与等待synchronized (this)的其他消费者线程竞争资源。这会导致竞争条件。但是为什么不简单地让.wait() 消费者持有资源,直到它存在synchronized 块?

【问题讨论】:

  • 你说的是wait()消费者之间的公平吗?
  • 好吧,如果另一个消费者也想要资源,你如何决定谁获得资源?我的意思是,你的解决方案是什么?如果多个消费者尝试获取资源,谁来决定首选哪个消费者?
  • 这不是竞争条件。这是不公平的,可能会导致饥饿。您通常需要做出决定以进行公平调度或获得最后一点性能。 Java 选择了后者。
  • @k5_ ... 并给了ReentrantLock 支持前者。
  • @AKSW 我的意思是,让.wait() 线程在睡眠时保持锁定。这样,同步块中将只有一个线程可以执行。

标签: java multithreading locking synchronized producer-consumer


【解决方案1】:

这是一个幼稚的问题。感谢 cmets,我想我现在理解了设计背后的逻辑:

  1. .wait() 线程在等待时不能只持有锁,因为那样生产者无法写入队列。
  2. .wait()线程唤醒时,为什么不能保证它得到锁呢?因为由于 #1 的原因,.wait() 线程必须在开始等待之前放弃资源。同时,其他消费者线程可以到达.wait() 阶段。既然有很多线程在等待,谁应该得到资源? Java 选择对所有线程一视同仁,更不用说等待时间了。

【讨论】:

  • Java 没有选择公平。你无法保证最先开始等待的线程会先获得锁。
  • @JBNizet 很好。误解了fairness的意思。
  • 不幸的是,Java 方法避免了公平性和确定性行为。 Java 中无法保证某个特定的等待线程会访问共享资源。平均而言,这是可行的,但行为的平均值并不是行为的保证。鉴于缺乏线程将访问共享资源的保证,很明显 Java 线程模型已被破坏。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-29
  • 1970-01-01
相关资源
最近更新 更多