2016-09-27 101 views
0

我有3个线程,所有3做同样的事情“[...]”(例如写入列表中,我们同步):死锁行为

public void run(){ 
    long time= System.currentTimeMillis(); 
    while(System.currentTimeMillis - time < 10000){ 
    synchronized(object){ 
     [...] 
     object.notifyAll(); 
     object.wait(); 
    } 
    } 
    System.out.println(Thread.currentThread.getName() + " just finished"); 
} 

我发现好奇的是,当一个线程退出while循环时,会发生死锁。我的问题不是它发生了,因为它正是我正在测试的,但是当它发生时。在两个线程完成后,不应该发生死锁,因为还有一个线程无法通过任何两个线程完成通知?
当然有一个机会,两个线程调用他们的“等待”在同一时间,所以我们得到的只是一个成品线后死锁,因为这两个等待那些无法通过完成一个被唤醒,但我已经运行测试很多次,结果总是相同的:在完成一个线程后死锁。

我错过了什么吗?

+1

线程在等待什么东西?见[这里](http://howtodoinjava.com/core-java/multi-threading/how-to-work-with-wait-notify-and-notifyall-in-java/)关于如何实际等待的一些文档为了某件事。 –

+1

在这种情况下,没有什么具体的他们正在等待。我在另一个环境中注意到了这种行为,并想为它编写一个简单的测试。这个问题有点泛泛,但我不确定如何对它进行描述。 我以为有三个线程,按照这个顺序等待并通知,只有当一个线程都不在时,才会导致死锁,因为几乎所有线程都会通知其他线程。 我知道等待等待是不明智的。也许我只是花太多时间去思考通常不会发生的事情(即没有条件的等待) – user6454491

+1

它只是不起作用。如果他们没有什么等待,他们就没有办法知道它是否已经发生。如果你等待已经发生的事情,你将永远等待。所以这是一个绝对不可能工作的设计,除了运气。要使用等待/通知你*必须*保持被等待的东西的状态。你不能等待没有特别的东西,它不会工作。 –

回答

1

wait功能会等待是否有什么东西要等待还是不行。在致电wait之前,您必须检查您想等待的事情是否已经发生 - 这就是您为什么在​​区块中的原因,以便持有保护您正在等待的共享状态的锁定。

如果没有某个共享状态,您将永远无法获得wait/notifyAll,您正在等待达到某个特定状态。您必须使用该锁来保护该共享状态,并且必须在调用wait之前检查其状态。否则,你将永远有可能的比赛,包括你所看到的那种即使已经发生也要等待发生的事情,从而永远等待。