倒计时和进一步同步

时间:2016-01-13 10:44:36

标签: java multithreading synchronization countdownlatch

据说我有以下类定义,当一个线程想要为多个(可能)等待线程设置一个时:

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进行额外的同步,或者需要变化吗?

2 个答案:

答案 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}}。