0

我们有两个线程,Thread2 等待 Thread1(从它接收消息)

class Thread1 .. {
 run() {
   synchronized(this) { some-work; notify(); } 
 }
}

class Thread2 .. {
 run() {
   while(true) {
    synchronized(thread1) {
      ...
      thread1.wait();
      ... 
      println("Got here"); // has received the notify() from Thread1   
    }
   }
 }

}

  1. thread2.start() // thred2首先准备好接收来自thread1的所有消息
  2. 线程1.start()

在按顺序启动这些线程后,我们遇到了 thread2 正在等待来自 thread1 的 notify() 的情况,这将在几分钟内发生 - 将出现消息“到达这里”。

但是,如果我在这里延迟:

 class Thread2
 run() {
       while(true) {
        sleep(1000);  // the dalay   
        synchronized(thread1) { ..
 }

然后消息'Got Here'将永远不会出现 - 因为 thread2 在达到 sycnronized(thread1) 之前会错过来自 thread1 的 notify() - 然后我们就会遇到Nothing To Wait的情况。

问题是:

1.这两行是原子的吗?或者更好地说,这两行之间的差距是原子的?:

 while(true) {
    // gap
    synchronized(thread1) {..thread.wait() ..} 
 }

2. 或者这是否意味着我们不应该在 while() 和同步块之间放置任何表达式?例如,我们可以:

 while(true) {
    int a = 0; a++; 
    synchronized(thread1) {..thread.wait() ..} 

因为我们在那里有这些表达,那么我们就有“无所事事”情况的风险?

4

3 回答 3

2

wait并且notify不足以创建信号机制,因为您已经发现:如果您没有任何服务员,则通知将进入位桶。

信号量就足够了:如果发送者在接收者做其他事情时返回许可,那么接收者将立即获得该许可。

但是,正如一些评论者所说,BlockingQueue是一个更好的解决方案,因为它意味着您的代码不必了解任何有关线程的知识。

于 2013-02-08T15:01:40.813 回答
1

行间没有间隙是“原子的”,原子性的概念在这里不适用。

如果您想避免错过通知,请在 thread2 的 run 方法的主体中启动 thread1。

于 2013-02-08T14:35:07.680 回答
1

实际上,您问如果没有 sleep() 是否会发生这种情况,对吗?恕我直言,答案是肯定的。虽然“差距”只是——没有——循环本身也包含实际的指令。在它们之间,线程可以切换。恕我直言,也不能保证您在 Thread1.run 之前到达 Thread2.run 只是因为您首先启动了 Thread2。不过,我不确定如何解决这个问题。也许让 Thread1 以某种方式等待 Thread2?

于 2013-02-08T14:36:13.673 回答