【问题标题】:What operations in Java are considered atomic?Java中的哪些操作被认为是原子的?
【发布时间】:2011-06-12 23:52:21
【问题描述】:

Java 中的哪些操作被认为是原子的?

【问题讨论】:

    标签: java multithreading atomic


    【解决方案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 是这个帖子中最有价值的评论。
    猜你喜欢
    • 2013-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-27
    • 1970-01-01
    • 1970-01-01
    • 2015-02-15
    相关资源
    最近更新 更多