让我们以SimpleDateFormat为例,因为它不是线程安全的。
我可以允许每个线程都有自己的SimpleDateFormat副本,使用这样的threadLocal:
private static final ThreadLocal<SimpleDateFormat> formatter = new ThreadLocal<SimpleDateFormat>(){
@Override
protected SimpleDateFormat initialValue()
{
return new SimpleDateFormat("yyyyMMdd HHmm");
}
};但是易失性关键字保证线程将拥有该变量的最新副本。所以我不能这样做吗?
volatile SimpleDateFormat myformatter;实现同样的线程安全?
发布于 2016-10-06 15:06:37
可变关键字确保线程将拥有该变量的最新副本。
仅适用于易失性变量,而不是其字段。
另外,只有当您需要更改变量的值时,volatile才会有用。在您的用例中,final看起来更合适:
private static final SimpleDateFormat format = ...这还保证了变量的最新值--因为它只能被赋值一次,而static final保证了类完全加载后的可见性。
但这并不是SimpleDateFormat不安全线程的原因:它具有可变状态,用于在格式化日期时存储中间值。
如果一个线程调用format,而另一个线程也在同一个SimpleDateFormatter实例的format方法中,这些中间变量就会被不可预测地践踏,导致线程之间的干扰,从而导致不可预测的输出。
这些中间变量的值在由另一个线程读/写时是否是最新的并不重要--它们的更新可以是间接性的。
简而言之,volatile并不能防止线程干扰,因此这里并不是ThreadLocal的适当替代方案。
发布于 2016-10-06 15:52:20
ThreadLocal是一种使线程能够拥有自己的对象本地副本的工具。ThreadLocals最好与线程限制的线程安全策略中的线程安全对象一起使用(即使对于许多不是“线程安全”的对象,只要不从受限线程中泄漏它们的引用,线程安全使用仍然是可能的)。ThreadLocals无法帮助在实例化这些对象的线程之外共享的可变对象的线程安全使用。
volatile关键字用于提供一个弱形式的线程安全,该变量可以被许多不同的线程访问。一个关键的区别是,ThreadLocals通常不会被多个线程访问。
一般说来,线程安全既需要可见性(对变量的最新更新应该对其他线程可见),也需要互斥(状态转换必须是原子的,这样状态就不会被观察到不一致)。Volatile与Java模型一起工作,以确保变量是可见的,但它不提供任何形式的互斥,因此不为对象中的状态转换提供原子性。
因为volatile和ThreadLocal有很大的不同,所以在任何情况下你都不可能用一个代替另一个。
发布于 2016-10-06 15:05:08
您不能与volatile实现相同的线程安全,因为在不同的线程中将使用相同的SimpleDateFormat实例。
https://stackoverflow.com/questions/39899420
复制相似问题