java - java 中的 volatile 与 threadLocal

标签 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");
    }
};

但是 volatile 关键字保证线程将拥有变量的最新副本。所以我可以不这样做吗:

volatile SimpleDateFormat myformatter;

并实现同样的线程安全?

最佳答案

the volatile keyword guarantees that a thread will have the most recent copy of the variable

volatile 变量,而不是它的字段。

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

private static final SimpleDateFormat format = ...

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


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

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

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

简而言之,volatile 不能防止线程干扰,因此这里不是 ThreadLocal 的合适替代方案。

关于java - java 中的 volatile 与 threadLocal,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39899420/

相关文章:

java - 如何对新的 Java Web 应用程序进行负载测试?

java - 定时器类中潜在的竞争条件?

并发问题(死锁?)

c++ - 在 C 中递增一个 volatile 变量

java - 通过其键的一部分从哈希表中获取值

java - 如何使用 Spark SQL 从外部查询中的子查询访问列

java - 未处理的异常 org.json.jsonexception

java - 在android中,如何将数据加载到它自己的线程中?

asp.net - 为什么/何时 session 写入容易受到线程终止的影响?

java - 返回 volatile 变量的函数是否需要同步?