侃volatile
volatile关键字是在很多Java的并发的框架中,或者并发场景下常用的关键字。有的地方描述它是一种轻量级的synchronized。这并没有错,怎样说都可以,但是千万不要把它当成锁或synchronized来看待,它有它的作用,但是实际上与锁相差甚远,甚至不会提供什么同步的机制。因此,只有详细理解了它的作用,才可以对它有很好的应用,不会“误以为它可以为我做到这种保护”,进而“引发重大的线程安全问题”。
作用
分成两点:- 对volatile变量的写操作保证可见性,不保证原子性;
 - 禁止指令重排序。
 
所有的volatile变量的写,会从硬件层面上进行控制,写完的值会直接写回主存(LOCK#信号),同时使其他的高速缓存缓存的值无效(Intel的MESI等)。另外对可能发生数据依赖的指令禁止重排序,使逻辑上相对安全。
接下来我将从原理角度解释为什么是这样。
JMM(Java内存模型)
首先,要理解多线程为什么会出错,需要理解一个抽象概念,也就是这个小标题《JMM》。在多线程模型中,应该这样表示Java的内存:

这里的本地内存,可以指线程的私有栈帧,或者负责处理这个线程的CPU的高速缓存等等。总之,所有变量,要在这里存一份。后续如果修改就对这个拷贝进行修改,直到写回到主内存,才算修改操作完成。不要纠结为什么,一切为了执行的效率,在这里写会更快,差个几十几百倍的都很常见。层级越高的高速缓存就越快。
说明这个的主要问题就是,在多线程中,一个线程的执行结果可能对另一个线程并不可见。常见的多线程例子,多个线程对一个共享变量进行累加,互相看不见别人加的结果,那中间必然有的操作丢失掉。
                    
                
                
            
        
浙公网安备 33010602011771号