0

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

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,根据定义这是线程安全的(除非你在其中做了一些愚蠢的事情)。那么,以这种方式使用不可重置标志是线程安全的吗?(如果是这样,它甚至会提供任何性能优势吗?)

谢谢

4

1 回答 1

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/

于 2013-05-09T00:52:56.973 回答