java中的volatile vs threadLocal

j2e*_*nue 6 java multithreading volatile thread-local

让我们以SimpleDateFormat为例,因为它不是线程安全的.

我可以允许每个线程使用threadLocal拥有自己的SimpleDateFormat副本,如下所示:

 private static final ThreadLocal<SimpleDateFormat> formatter = new ThreadLocal<SimpleDateFormat>(){
    @Override
    protected SimpleDateFormat initialValue()
    {
        return new SimpleDateFormat("yyyyMMdd HHmm");
    }
};
Run Code Online (Sandbox Code Playgroud)

但volatile关键字保证线程将拥有该变量的最新副本.所以我不能这样做:

volatile SimpleDateFormat myformatter;
Run Code Online (Sandbox Code Playgroud)

并实现相同的线程安全?

And*_*ner 5

volatile 关键字保证线程将拥有变量的最新副本

volatile 变量,而不是其字段。

此外,volatile仅当您需要更改变量的值时才有用。在您的用例中,final看起来更合适:

private static final SimpleDateFormat format = ...
Run Code Online (Sandbox Code Playgroud)

这也保证您将拥有变量的最新值 - 因为它只能被分配一次其值,并且static final一旦类完全加载就保证可见性。


但这SimpleDateFormat并不是线程安全的原因:它具有可变状态,用于在格式化日期时存储中间值。

如果一个线程调用format而另一个线程也在format同一个SimpleDateFormatter实例的方法中,这些中间变量会被不可预测地踩踏,导致线程之间的干扰,从而导致不可预测的输出。

当被另一个线程读/写时,这些中间变量的值是否是最新的并不重要——它们的更新可以穿插。

简而言之,volatile不会阻止线程干扰,因此不是ThreadLocalhere的合适替代方案。