volatile - JiyangM/spring GitHub Wiki

参考《java高并发编程详解》

优点:

  • 保证了并发编程的可见性;
  • 保证了并发编程的有序性;

(1 . 保证了不同线程对该变量操作的内存可见性)

(2 . 禁止指令重排序)

原理:

  • 每一个线程在运行时,都有自己的一个本地内存。
  • 共享编程存在于主内存中。
  • 当某个线程对共享编程操作的时候,首先将数据读入到本地内存中。
  • 如果某个线程进行的是修改操作,则会强制将结果刷入到主内存中,并且其他线程的变量副本失效,需要重新到主内存中获取,从而保证了内存可见性。

使用场景:

  • 可见性-开关控制
 public static class Task implements Runnable {

        private volatile boolean init = true;

        @Override
        public void run() {
            while (init) {

            }
        }

        public void shutDown() {
            init = false;
        }
    }

当一个线程调用shutDown后,init 的值被更改,其他线程可见性原则会获取新的值。

  • 顺序性 参考《顺序性原则》。

可以用volatile的地方:对一个变量,更新其值的时候不依赖于当前值,且该变量不会和其他一起构成一个不可变条件。


什么是内存屏障(Memory Barrier)?

插入一个内存屏障,相当于告诉CPU和编译器先于这个命令的必须先执行,后于这个命令的必须后执行。内存屏障另一个作用是强制更新一次不同CPU的缓存。

内存屏障(memory barrier)和volatile什么关系?

从Load到store到内存屏障,一共4步,其中最后一步jvm让这个最新的变量的值在所有线程可见,也就是最后一步让所有的CPU内核都获得了最新的值,但中间的几步(从Load到Store)是不安全的,中间如果其他的CPU修改了值将会丢失。 因为volatile保证变量对线程的可见性,但不保证原子性。

AtomicLong来说,它既解决了上述的volatile的原子性没有保证的问题,又具有可见性。它是如何做到的?当然就是上文《非阻塞同步算法与CAS(Compare and Swap)无锁算法》提到的CAS(比较并交换)指令。

https://www.cnblogs.com/xrq730/p/7048693.html https://juejin.im/post/5a2b53b7f265da432a7b821c https://my.oschina.net/tantexian/blog/808032