Java中的哪些操作被认为是原子的?
Posted
技术标签:
【中文标题】Java中的哪些操作被认为是原子的?【英文标题】:What operations in Java are considered atomic? 【发布时间】:2011-06-12 23:52:21 【问题描述】:Java 中的哪些操作被认为是原子的?
【问题讨论】:
【参考方案1】: 除了 long 和 double 之外的所有基本类型的赋值 引用的所有分配 volatile 变量的所有赋值 java.concurrent.Atomic* 类的所有操作也许还有更多。看jls。
如 cmets 中所述,原子性并不意味着可见性。因此,虽然可以保证另一个线程不会看到部分写入的 int
,但它可能永远不会看到新值。
long 和 double 上的操作是在常见的 64 位 CPU atomic as well 上进行的,尽管不能保证。另请参阅feature request。
【讨论】:
另外,请记住,虽然操作是原子的,但在多线程应用程序中可能无法保证这些操作的可见性,除非特别注意(此处的详细信息是方式 复杂地在评论中描述..)64 bit jvm, long and double assignments are also atomic.
你确定吗?我会说它们用于编译代码,但是解释代码呢?可能你是对的,但有什么保证吗?
规范仍然没有强制要求 64 位 JVM 为 long 和 double 赋值提供原子性。 java.sun.com/docs/books/jls/third_edition/html/memory.html#17.7 用它著名的话说,“这种行为是特定于实现的”。但是,64 位 VM 更有可能将其实现为原子操作。
您确定引用分配是原子的吗?如果是这样,那么为什么存在 AtomicReference 类? download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/…
恕我直言,正常的引用分配是原子的,但 AtomicReference 提供了更多:compareAndSet 和 getAndSet,如果没有同步,这是您无法实现的。【参考方案2】:
在Java中,32位或更小量的读写保证是原子的。 原子,我们的意思是每个动作都在一个步骤中发生并且不能被打断。因此,当我们有多线程应用程序时,读写操作是线程安全的,不需要同步。
例如,以下代码是线程安全的:
public class ThreadSafe
private int x;
public void setX(int x)
this.x = x;
【讨论】:
..threadsafe 从某种意义上说,该值将始终完全是原始值或设定值。由于缺乏“易失性”或“同步”,大多数最新值仍然不一定对其他线程可见。 +1 @MikkoWilkman 所说的。不应使用那段代码,因为从内存可见性的角度来看,它绝对不是线程安全的。【参考方案3】:根据 AtomicLong.java 中的这个方法,long 的赋值似乎是原子的:
public final void set(long newValue)
value = newValue;
注意没有任何同步。
【讨论】:
看value
的声明。这是volatile
。
value
是volatile
不会使value
的分配原子化,它只是避免了“发布”问题。
两者都有,请参阅JLS, section 17.7:对 volatile long 和 double 值的写入和读取始终是原子的。
在我看来,@LyleZ 是这个帖子中最有价值的评论。以上是关于Java中的哪些操作被认为是原子的?的主要内容,如果未能解决你的问题,请参考以下文章
什么是原子操作?在 Java Concurrency API 中有哪些原 子类(atomic classes)?