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 valuevolatile 不会使value 的分配原子化,它只是避免了“发布”问题。 两者都有,请参阅JLS, section 17.7:对 volatile long 和 double 值的写入和读取始终是原子的。 在我看来,@LyleZ 是这个帖子中最有价值的评论。

以上是关于Java中的哪些操作被认为是原子的?的主要内容,如果未能解决你的问题,请参考以下文章

什么是原子操作?在 Java Concurrency API 中有哪些原 子类(atomic classes)?

什么是原子操作?在 Java Concurrency API 中有哪些原 子类(atomic classes)?

并发编程Java中的原子操作

原子操作的特性

Java 高并发三 Java内存模型和线程安全详解

Java高并发程序设计—— java内存模型和线程安全