据说我有以下类定义,当一个线程想要为多个(可能)等待线程设置一个时:
public class A {
private int a;
private CountDownLatch gate;
public A(int a) {
a = 1;
gate = new CountDownLatch(1);
}
public int getA() {
latch.await();
return a;
}
public void setA(int a) {
this.a = a;
gate.countDown();
}
}
在我看来,需要变得不稳定,但我不确定......有人可以分享为什么,如果有的话,需要围绕getA进行额外的同步,或者需要变化吗?
答案 0 :(得分:2)
根据the javadoc:
在计数达到零之前,调用
Sub LoopThroughFolder() Dim MyFile As String, Str As String, MyDir As String, Wb As Workbook Dim Rws As Long, Rng As Range Dim fExt, ext Set Wb = ThisWorkbook 'change the address to suite MyDir = "C:\TestWorkBookLoop\" ChDir MyDir Application.ScreenUpdating = 0 Application.DisplayAlerts = 0 fExt = Array("*.xlsx", "*.xls") 'file extensions, set the file extensions of the files to move For Each ext In fExt 'loop through file extensions MyFile = Dir(MyDir & ext) Do While MyFile <> "" Workbooks.Open (MyFile) Sheets(1).Name = "MySheet" With ActiveWorkbook .Save .Close End With MyFile = Dir() Loop Next ext End Sub
之前的线程中的操作发生在从另一个线程中的相应countDown()
成功返回之后的操作之前。
如果您只拨打await()
一次,那么您就不需要额外的同步。如果你第二次打电话,因为计数已经是0,你将得不到同样的保证。
如果预期的用途是只调用setA
,如果多次调用它来强制执行该合同,则可以调用setA
(尽管检查计数并为原子分配新值可能会很棘手额外的同步)。
如果您对setA
可以多次调用感到满意,那么您需要进行额外的同步。
答案 1 :(得分:2)
实际上a
并不需要变得不稳定,因为countDown()
会将state
存储到AbstractQueuedSynchronizer
CountDownLatch
变量setA()
中new CountDownLatch(1)
。易失性存储会触发内存屏障(great in-depth article about Memory Barriers and etc in JSR-133)。根据JMM,所有以前的存储(对于其他变量)都可以被其他线程看到。
assylias 是正确的,只有在您拨打{{1}}一次时才会出现这种情况,因为您将闩锁构建为{{1}}。