Java中不可重置的“标志”线程是否安全?

时间:2013-05-09 00:34:41

标签: java asynchronous thread-safety

我一直在使用这种模式,但我最近才开始认为这样做可能不太好。基本上,我使用了这种模式的一些变体:

public class SampleJavaAsync
{
    public SampleJavaAsync() { }

    private boolean completed;
    public void start()
    {
        new Thread(new Runnable() {
            @Override
            public void run() {
                //... do something on a different thread
                completed = true;
            }
        }).start();
    }

    public void update()
    {
        if (!completed) return;
        //... do something else
    }
}

*用户有责任确保start仅被调用一次。无论何时何地都会调用update

我一直认为这在Java中是线程安全的,因为即使没有严格的同步,我也只是将completed设置为true。一旦观察到true,它就不会重置为false。它在构造函数中初始化为false,根据定义,它是线程安全的(除非你在其中做了一些愚蠢的事情)。那么,以这种方式使用不可复制的标志是否安全? (如果是这样,它甚至可以提供任何性能优势吗?)

由于

1 个答案:

答案 0 :(得分:3)

Java:update()可以看到已经发生的更新完成。除非你将它标记为volatile,否则允许JVM以优化的名义进行各种操作(即按照它认为合适的方式重新排序读取和写入),这意味着你可以切实地运行一个运行update()的线程的状态。已完成已更改,因为它没有标记为易失性,并认为它可以优化那个讨厌的写入(或推迟)。

在第一次设置时,您至少会冒不一致的风险,例如,在同一个线程上调用update()可能会看到与来自另一个线程的同一调用不同的值。

更好的解释:

http://jeremymanson.blogspot.com/2008/11/what-volatile-means-in-java.html

或者,如果您真的对Java中的并发感到好奇,请购买JCIP的副本:

http://jcip.net.s3-website-us-east-1.amazonaws.com/