volatile简介与原理
一、计算机内存模型
1. CPU的高速缓存:
a. 由于CPU的速度远远大于IO速度和主存速度,所以CPU加了一层高速缓存,把主存的数据加载到高速缓存
b. CPU高速缓存为某个CPU独有,只与运行在该CPU的线程有关
2. 缓存一致性问题:
a. 当一个在主存里的变量被多个线程访问,成为共享变量,每个线程会把共享变量拷贝到当前线程的高速缓存,操作完后更新回主存
b. 可能一个线程操作的变量,被别的线程已经更新了,但是当前线程不知道
二、Java内存模型JMM
1、Java内存模型规定所有的变量都是存在主存当中(类似于前面说的物理内存),每个线程都有自己的工作内存(类似于前面的高速缓存)
2. 线程对变量的所有操作都必须在工作内存中进行,而不能直接对主存进行操作
3. 并且每个线程不能访问其他线程的工作内存
三、并发编程
1. 要想并发程序正确地执行,必须要保证原子性、可见性以及有序性,只要有一个没有被保证,就有可能会导致程序运行不正确
2. 原子性:一个操作要么不执行,要么全执行
3. 可见性:当一个线程修改了共享变量,其他线程立即可见
4. 有序性:代码执行是有先后顺序的,JVM会进行指令重排,指令重排不会影响单线程的操作结果,但有可能影响多线程的结果
四、volatile关键字
1. volatile关键字轻量级的synchronized,保证多线程正确执行
2. 可见性:
a. 当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去内存中读取新值,即更新会被其他线程看见
b. 通过synchronized和Lock也能够保证可见性,synchronized和Lock能保证同一时刻只有一个线程获取锁然后执行同步代码,但是synchronized会引起线程上下文切换,没有volatile性能好
3. 原子性
a. volatile无法保证原子性,可以用synchronized、Lock、AtomicInteger保证原子性
b. Java内存模型只保证了基本读取和赋值是原子性操作;而自增操作是不具备原子性的,因为它包括读取变量的原始值、进行加1操作、写入工作内存
4. 有序性:volatile通过禁止指令重排保证有序性
四、volatile实现原理
1. 汇编后的代码加入了lock,相当于内存屏障
2. 内存屏障的作用:禁止指令重排,线程里的数据立即刷新回主存
五、使用场景
1. 标志位:bool flag=true
2. 单例双重检查
参考:
http://www.cnblogs.com/dolphin0520/p/3920373.html
https://www.cnblogs.com/chenssy/p/6379280.html