有一个主线程有一个while循环,在此期间,当他检查一些条件时,如果满足所有条件,他将启动另一个线程进入wait()状态。等待并通知协调
并行运行的其他线程在工作完成时通知主线程。
当“子线程”在之前通知主线程时,主线程进入等待状态=死锁存在问题。
避免它的最佳做法是什么?
有一个主线程有一个while循环,在此期间,当他检查一些条件时,如果满足所有条件,他将启动另一个线程进入wait()状态。等待并通知协调
并行运行的其他线程在工作完成时通知主线程。
当“子线程”在之前通知主线程时,主线程进入等待状态=死锁存在问题。
避免它的最佳做法是什么?
只要确保主线程不会等待已发生的事情。 (为什么有人会那样做呢?这没有任何意义。)
我宁愿使用明确的Locks。请参阅Java Concurrent Api。
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/Lock.html
使用旗语的通知。
就是这样,真的。信号量有一个计数,并可以记录通知,直到主线程开始等待。
简单的答案是使用Java 5中的并发包。CountDownLatch在这里看起来很合适。
如果您仅限于Java 5之前的环境,则必须创建一个使用相同算法的自定义实现。创建所有子线程后,主线程将调用signalReady。子线程在完成工作后会调用signalComplete。
一个简单的实现是将一个名为Latch的Object带有两个两个成员字段。
以下实施将适用于一位家长和一位子女。对于额外的孩子,每个孩子在完成时都可以给自己的闩锁发出信号。仍然会有这种情况会导致竞赛状况。在信号之间添加旋转锁定或可能是睡眠会降低竞争条件的可能性。 它不会消除它
class Latch{
Object readyLock;
Object completeLock;
public void signalComplete(){
synchronized(readyLock){
readyLock.wait()
}
//spin lock as a precaution
synchronized(completeLock){
completeLock.notify()
}
}
public void signalReady(){
synchronized(readyLock){
readyLock.notify()
}
synchronized(completeLock){
completeLock.wait()
}
}
}
希望这有助于!
这段代码被破坏严重,并造成OP询问的问题!即使没有什么需要等待,signalReady函数也会等待。 'signalComplete'函数完成同样的事情。 – 2012-07-18 07:18:19
这是一个非常普遍的做法几乎总是把wait()
方法在while
循环,其“迭代条件”是检查是否已经发生特定事件时,发生其中的其他线程会被称为notify()
方法。
例如:
while(!event_occurrence) {
...
wait();
...
}
其中event_occurrence
是其另一个线程会叫notify()
法事件。
我不认为这将有助于:如果有2个子线程。第一个子线程完成=> event_occurrence = true,主线程进入while循环。此时(执行wait()之前)子线程2完成。那么主线程再次执行wait()=>死锁 – markiz 2012-07-18 07:32:12
@markiz:子线程2无法完成,除非此线程处于“等待”状态,因为此线程持有锁。 (它调用'wait'来释放锁以及等待事件。) – 2012-07-18 08:31:50
@David Schwartz,锁定主线程。子线程唤醒主线程。主线程产生子线程并等待它们中的任何一个完成。然后他做了一些逻辑并再次入睡。 – markiz 2012-07-18 09:52:44
+1:wait()的javadoc明确地解释了应始终有一个循环检查进入/退出等待状态的条件。 – 2012-07-18 05:49:50