让我们以 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/