如果读写是原子的,为啥需要 volatile [重复]

Posted

技术标签:

【中文标题】如果读写是原子的,为啥需要 volatile [重复]【英文标题】:Why is volatile needed if reads and writes are atomic [duplicate]如果读写是原子的,为什么需要 volatile [重复] 【发布时间】:2020-02-05 02:32:58 【问题描述】:

Oracle documentation 声明:

对于引用变量和大多数原始变量(除 long 和 double 之外的所有类型)而言,读取和写入是原子的

现在我想知道为什么在下面的示例中需要使用 volatile 关键字来防止无限循环 - int 变量的更改应该是原子的,因此每个人都可以立即看到,不是吗?

public class HelloWorld

     // This doesn't work as expected
     private static int x = 0;
     //Following would work: private volatile static int x = 0;

     public static void main(String []args) throws Exception
     
         Thread t1 = new Thread(() -> 
            try
            
                Thread.sleep(1000);
                x = 1; //Should be atomic, right? 
             catch (InterruptedException e) 
        );

         System.out.println("Begin");
         t1.start();

         //The evaluation of the condition should also be atomic, right?
         while(x == 0)
         
         

         t1.join();
         System.out.println("End");
     

【问题讨论】:

原子性不是问题——你查过 Java 中 volatile 的含义吗?例如,tutorials.jenkov.com/java-concurrency/volatile.html,尽管到处都在讨论它。 “原子”并不意味着“立即对所有人可见”。当一个线程对某些数据执行原子操作时,这意味着其他线程要么看到它已完全完成,要么他们将看到它根本没有完成。没有其他线程会看到处于操作仅完成部分状态的数据。 【参考方案1】:

读写是原子的,只是线程之间不一定可见

需要volatile 来创建happens-before 关系:没有它,一个线程中的写入和另一个线程中的读取之间的顺序无法保证。

通过标记变量volatile,保证一个线程中的写入对所有后续读取都是可见的(直到下一次写入,obv):写入提交到主存,然后从主存读取,而不是缓存中保存的值。

【讨论】:

以上是关于如果读写是原子的,为啥需要 volatile [重复]的主要内容,如果未能解决你的问题,请参考以下文章

volatile

volatile

volatile为啥不能保证原子性

为什么volatile++不是原子性的?

为什么volatile++不是原子性的?

java单例双重检查锁为啥需要加volatile关键字