【发布时间】:2011-08-12 06:45:03
【问题描述】:
所有其他原子对象都一样吗?更容易解释 AtomicInteger 的问题。由于超过 1 个线程正在访问对 myInt 的引用,难道不是一个线程可以看到该对象的注册缓存值,例如 null,除非它也被声明为 volatile?如果不是怎么来的?
【问题讨论】:
-
我尝试将所有 AtomicReference 字段设为最终字段。您应该避免更改它。
标签: java thread-safety
所有其他原子对象都一样吗?更容易解释 AtomicInteger 的问题。由于超过 1 个线程正在访问对 myInt 的引用,难道不是一个线程可以看到该对象的注册缓存值,例如 null,除非它也被声明为 volatile?如果不是怎么来的?
【问题讨论】:
标签: java thread-safety
不仅没有必要,而且实际上在语义上是错误的。 AtomicReference 在自身内部保存“真实”引用,并使用自己的同步结构管理对它的访问。 JVM 自己的同步构造(synchronized、volatile 等)未使用。 AtomicReference 对象本身不应被视为易失性。如果有的话,请考虑将其设为final。
还可以考虑this question - 如果您只需要获取和设置操作,volatile 可以被视为使用 AtomicReference 的替代方法。
【讨论】:
volatile AtomicReference,那几乎肯定不是作者想要的。
“原子”对象不是不可变的,因此只有在正确发布时它们才应该是线程安全的。例如,当您执行此类操作时,您将需要使用 volatile 关键字。
volatile AtomicInteger counter = // initialize counter
int harvest(){
AtomicInteger old = counter;
counter = new AtomicInteger();
return old.get();
}
如果您从上述代码中删除 volatile,您确实可能会丢失一些增量。根据规范,您还可能获得对未完全构造的 AtomicInteger 对象的引用,从而获得未定义的行为。
那么,您需要将您的原子对象声明为 volatile 吗?答案是视情况而定。只要它们被正确发布,它们就是线程安全的,就像任何其他线程安全的对象一样(不可变对象除外,这是特殊情况)。在大多数情况下,您应该将它们设为最终版本。
【讨论】: