假设我有以下代码:
public class CountDownLatchExample { // Note : Exception handling ommited
void main(){
CountDownLatch startSignal = new CountDownLatch(1);
CountDownLatch doneSignal = new CountDownLatch(N_PARTIES);
for(int i = 0; i < N_PARTIES; i++){ // create and start threads
new Thread(() -> {
startSignal.await(); // Wait startSignal before doing Work
doWork();
doneSignal.countDown();
}).start();
}
// (...) do something else // Don't let run yet
startSignal.countDown(); // Let all threads proceed
// (...) do something else
doneSignal.await(); // Wait for all threads to finish
}
}
主线程创建并启动工作线程。在run
方法中,其他线程等待,直到主线程调用startSignal.countDown()
, 然后才能调用doWork()
和doneSignal.countDown()
。
我知道调用线程的countDown()
与从await
返回的线程之间存在happens-before关系, 那么如果一个线程调用doneSignal.countDown()
,它所做的事情对所有其他线程都是可见的。
但我的问题是run()
方法是否按顺序执行,是否需要添加同步?
因为当调用startSignal.countDown()
时,所有线程都可以执行run
方法,但是假设在doWork()
方法中有一些共享变量发生了变化,或者只是同时执行run()
,可能会有三个线程同时执行doWork()
,然后其中两个在线程调用doneSignal.countDown()
之前被调度出去了,第三个线程调用了doneSignal.countDown()
。在这种情况下,happens-before关系有点无用,因为其他两个线程已经执行了doWork()
,只需要调用doneSignal.countDown()
,因为它们没有看到第三个线程所做的事情,因为它们一起执行了doWork()
。