假设我有以下代码:
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
方法中,其他线程等到main线程调用startSignal.countDown()
,然后就可以调用doWork ()
和 doneSignal.countDown()
。
我知道一个线程调用的countDown()
和从await
返回的线程之间存在happens-before关系,那么如果一个线程调用doneSignal.countDown()
,它所做的对所有其他线程都是可见的。
但是我的问题是run()
方法是不是顺序执行的,是否需要加同步??
因为当startSignal.countDown()
被调用时,所有线程都可以执行run
方法,但是假设在doWork()
> method 有一些共享变量发生变化,或者也只是并发执行 run()
,可能有三个线程同时执行 doWork()
,然后两个它们被安排在 doneSignal.countDown() 之前,第三个调用 doneSignal.countDown()。如果其他两个线程已经执行了 doWork() 并且他们只需要调用 doneSignal.countDown(),那么 happens-before 关系在这里有点无用,因为他们没有看到第三个线程做了什么,因为他们执行了 doWork ()“一起”。
最佳答案
CountDownLatch
不保证per mutual exclusion共享数据的访问,而是这种机制用于同步——在一个等待另一个的意义上——彼此之间的并行任务。类似于 Cyclic barrier 提供的功能.实际上,正如您所描述的,这就是您在代码中使用此机制的原因;协调 main 和其余线程的执行。
如果 doWork() 方法包含线程之间的共享状态,并发修改,那么您可能有竞争条件。因此,您需要使用例如 synchronized 子句确保共享的互斥。
关于java - Java 中的 CountDownLatch 需要额外的同步吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65655480/