是什么?
    volatile算是一种轻量级的synchronized,保证了可见性,有序性,还有部分的原子性,虽然synchronized可以保证这三点,但是相比synchronized来说volatile不会有阻塞带来的性能问题(虽然synchronized优化了很多,但是在读多的情况下,volatile性能更好,缓存失效导致volatile其实写性能也不是比synchronized性能好太多),所以能用volatile解决问题就使用volatile

    可见性是什么?怎么实现的?
    可见性就是对于被volatile修饰的变量来说,一个线程对这个变量的修改对另外一个线程是可见的,jvm层面是使用内存屏障,底层是使用了一个lock前缀的指令,这个指令能让对应处理器的缓存写回内存,然后其他处理器因为遵守了MESI缓存一致性协议就会在总线上嗅探自己的缓存数据是不是过期了,然后将对应的缓存做失效处理(早期都是通过锁总线的形式解决缓存不一致的问题的)
    有序性?
    volatile可以防止指令重排,因此可以保证有序性
    底层实现是通过在编译期生成字节码的时候插入内存屏障来实现的,它保证了对一个volatile变量写时不管前面的操作是什么也不能重排序到volatile后面,然后对一个volatile变量读时不管后面操作是什么都不能重排序到前面,先写后读不能重排序
    原子性?(volatile写前后插入写写屏障和写读屏障,volatile读后面插入读读屏障和读写屏障)
    因为内存屏障相当于一个数据同步点,他要保证在这个同步点之后的读写操作必须在这个点之前的读写操作都执行完之后才可以执行。
    因为happens-before原则里面有条原则是对一个volatile的写happens-before对一个volatile变量的读,因此可以保证部分的原子性,但是不能保证复合操作的原子性

    场景:

    扩展:
    我们在内存模型是怎么解决缓存一致性问题的?一文中介绍过缓存缓存一致性协议,同时也提到过内存一致性模型的实现可以通过缓存一致性协议来实现。同时,留了一个问题:已经有了缓存一致性协议,为什么还需要volatile?
    这个问题的答案可以从多个方面来回答:

    1、并不是所有的硬件架构都提供了相同的一致性保证,Java作为一门跨平台语言,JVM需要提供一个统一的语义。 2、操作系统中的缓存和JVM中线程的本地内存并不是一回事,通常我们可以认为:MESI可以解决缓存层面的可见性问题。使用volatile关键字,可以解决JVM层面的可见性问题。 3、缓存可见性问题的延伸:由于传统的MESI协议的执行成本比较大。所以CPU通过Store Buffer和Invalidate Queue组件来解决,但是由于这两个组件的引入,也导致缓存和主存之间的通信并不是实时的。也就是说,缓存一致性模型只能保证缓存变更可以保证其他缓存也跟着改变,但是不能保证立刻、马上执行。