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

猜你喜欢

转载自www.cnblogs.com/june0816/p/6102257.html