Java 中的 CountDownLatch 需要额外同步吗?
CountDownLatch in Java need additional synchronization?
假设我有以下代码:
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
}
}
main 线程创建并启动工作线程。在run
方法中,其他线程等待main线程调用startSignal.countDown()
,然后就可以调用doWork()
和doneSignal.countDown()
.
我知道线程调用的 countDown()
和来自 await
的 return 线程之间存在先行关系,那么如果线程调用 doneSignal.countDown()
, 它所做的对所有其他线程都是可见的。
但是我的问题是run()
方法是否顺序执行,是否需要加同步??
因为在调用startSignal.countDown()
时,所有线程都可以执行run
方法,但是假设在doWork()
方法中有一些共享变量发生变化,或者也只是并发执行 run()
,可能有三个线程同时执行 doWork()
,然后其中两个线程在 doneSignal.countDown() 之前调度,第三个线程调用 doneSignal.countDown()。如果其他两个线程已经执行了 doWork() 并且它们只需要调用 doneSignal.countDown(),那么 happens-before 关系在这里有点无用,因为它们没有看到第三个线程做了什么,因为它们“一起”执行 doWork()。
CountDownLatch
不保证每mutual exclusion of the accesses to the share data, rather this mechanism is used to synchronized -- in the sense of one waiting for the other -- parallel task among each other. Similar to the functionality provided by a Cyclic barrier。实际上,正如您所描述的,这就是您在代码中使用此机制的原因;协调 main 和其余线程的执行。
如果 doWork() 方法包含线程之间的共享状态,并发修改,那么您可能有 race-condition。因此,您需要使用 synchronized 子句确保共享的互斥。
假设我有以下代码:
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
}
}
main 线程创建并启动工作线程。在run
方法中,其他线程等待main线程调用startSignal.countDown()
,然后就可以调用doWork()
和doneSignal.countDown()
.
我知道线程调用的 countDown()
和来自 await
的 return 线程之间存在先行关系,那么如果线程调用 doneSignal.countDown()
, 它所做的对所有其他线程都是可见的。
但是我的问题是run()
方法是否顺序执行,是否需要加同步??
因为在调用startSignal.countDown()
时,所有线程都可以执行run
方法,但是假设在doWork()
方法中有一些共享变量发生变化,或者也只是并发执行 run()
,可能有三个线程同时执行 doWork()
,然后其中两个线程在 doneSignal.countDown() 之前调度,第三个线程调用 doneSignal.countDown()。如果其他两个线程已经执行了 doWork() 并且它们只需要调用 doneSignal.countDown(),那么 happens-before 关系在这里有点无用,因为它们没有看到第三个线程做了什么,因为它们“一起”执行 doWork()。
CountDownLatch
不保证每mutual exclusion of the accesses to the share data, rather this mechanism is used to synchronized -- in the sense of one waiting for the other -- parallel task among each other. Similar to the functionality provided by a Cyclic barrier。实际上,正如您所描述的,这就是您在代码中使用此机制的原因;协调 main 和其余线程的执行。
如果 doWork() 方法包含线程之间的共享状态,并发修改,那么您可能有 race-condition。因此,您需要使用 synchronized 子句确保共享的互斥。