简体   繁体   English

java中的volatile vs threadLocal

[英]volatile vs threadLocal in java

Lets take SimpleDateFormat as an example since it is not thread safe. 让我们以SimpleDateFormat为例,因为它不是线程安全的。

I could allow each thread to have its own copy of SimpleDateFormat using threadLocal like this: 我可以允许每个线程使用threadLocal拥有自己的SimpleDateFormat副本,如下所示:

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

But the volatile keyword guarantees that a thread will have the most recent copy of the variable. 但volatile关键字保证线程将拥有该变量的最新副本。 So could i not do this instead: 所以我不能这样做:

volatile SimpleDateFormat myformatter;

and achieve the same thread safety ? 并实现相同的线程安全?

the volatile keyword guarantees that a thread will have the most recent copy of the variable volatile关键字保证线程将拥有该变量的最新副本

Of the volatile variable only , not its fields. 只有 volatile变量,而不是它的字段。

Also, volatile is only useful if you need to change the value of the variable. 此外, volatile仅在您需要更改变量值时才有用。 In your use case, final looks like it would be more appropriate: 在您的用例中, final看起来更合适:

private static final SimpleDateFormat format = ...

This also guarantees that you will have the most recent value of the variable - because it can only be assigned its value once, and static final has guarantees the visibility once the class is fully loaded. 这也保证了你将获得变量的最新值 - 因为它只能被赋值一次,而static final在类完全加载后保证了可见性。


But this isn't the reason why SimpleDateFormat is not thread safe anyway: it has mutable state which it uses to store intermediate values when formatting the date. 但这并不是SimpleDateFormat无论如何都不是线程安全的原因:它具有可变状态,用于在格式化日期时存储中间值。

If one thread calls format while another is also in the format method for the same SimpleDateFormatter instance, these intermediate variables get stomped unpredictably, leading to interference between the threads, and hence unpredictable output. 如果一个线程调用format而另一个线程也在同一个SimpleDateFormatter实例的format方法中,则这些中间变量会不可预测地被踩踏,从而导致线程之间的干扰,从而导致不可预测的输出。

It doesn't matter whether or not the values of these intermediate variables are up-to-date when read/written by another thread - their updating can be interspersed. 在由另一个线程读取/写入时,这些中间变量的值是否是最新的并不重要 - 它们的更新可以散布。

In short, volatile doesn't prevent thread interference, and so is not an appropriate alternative to a ThreadLocal here. 简而言之, volatile不会阻止线程干扰,因此这里不是ThreadLocal的合适替代品。

ThreadLocal is a facility which enables threads to have their own local copy of an object. ThreadLocal是一种工具,它使线程拥有自己的对象本地副本。 ThreadLocals are best used with objects that can be thread safe within a thread safety policy of thread confinement (even for many objects that are not "thread safe", thread safe usage is still possible as long as no reference to them leaks out from the confining thread). ThreadLocals最适用于在线程限制的线程安全策略中可以线程安全的对象(即使对于许多不是“线程安全”的对象,只要没有对它们的引用从限制中泄漏,线程安全使用仍然是可能的线)。 ThreadLocals can not help with thread safe usage for mutable objects that are shared outside the thread that instantiates them. ThreadLocals无法帮助在实例化它们的线程之外共享的可变对象的线程安全使用。

The volatile keyword is used to provide a weak form of thread safety with a variable that may accessed by many different threads. volatile关键字用于通过可由许多不同线程访问的变量提供弱形式的线程安全性。 A key difference is that ThreadLocals are most typically not accessed by more than one thread. 一个关键的区别是ThreadLocals通常不被多个线程访问。

Broadly speaking, thread safety requires both visibility (the most recent updates to the variable should be visible to other threads) and mutual exclusion (state transitions must be atomic so that state can not be observed to be inconsistent). 从广义上讲,线程安全需要可见性(变量的最新更新应该对其他线程可见)和互斥(状态转换必须是原子的,以便不能观察到状态不一致)。 Volatile works with the Java Memory Model to guarantee that the variable will be visible, but it provides no form of mutual exclusion and therefore does not provide atomicity to state transitions in objects. Volatile与Java Memory Model一起使用以保证变量可见,但它不提供任何形式的互斥,因此不会为对象中的状态转换提供原子性。

Because volatile and ThreadLocal are so different, there really is no common circumstance in which you'd be able to substitute one for the other. 因为volatileThreadLocal是如此不同,所以实际上没有一个常见的情况可以用一个代替另一个。

您没有使用volatile实现相同的线程安全volatile因为SimpleDateFormat相同实例将在不同的线程中使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM