我一直在使用这种模式,但我最近才开始认为这样做可能不太好。基本上,我使用了这种模式的一些变体:
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,根据定义,它是线程安全的(除非你在其中做了一些愚蠢的事情)。那么,以这种方式使用不可复制的标志是否安全? (如果是这样,它甚至可以提供任何性能优势吗?)
由于
答案 0 :(得分:3)
Java:update()可以看到已经发生的更新完成。除非你将它标记为volatile,否则允许JVM以优化的名义进行各种操作(即按照它认为合适的方式重新排序读取和写入),这意味着你可以切实地运行一个运行update()的线程的状态。已完成已更改,因为它没有标记为易失性,并认为它可以优化那个讨厌的写入(或推迟)。
在第一次设置时,您至少会冒不一致的风险,例如,在同一个线程上调用update()可能会看到与来自另一个线程的同一调用不同的值。
更好的解释:
http://jeremymanson.blogspot.com/2008/11/what-volatile-means-in-java.html
或者,如果您真的对Java中的并发感到好奇,请购买JCIP的副本: