一:现象说明
- A B两个线程都访问到一个变量,若B修改了该变量,则A不一定马上知道该变量被改变了
- volatile关键字,使一个变量在多个线程间可见
- 使用volatile关键字修饰变量,会使得所有线程都会实时读到变量修改后的值
使用volatile前: 输出结果: 使用volatile后输出结果:
二:volatile的作用
1.保证线程的可见性
多个线程都会有共享内存,每个线程都会有自己单独的工作内存,每个线程都会将共享内存中的变量复制一份到自己的工作内存以供使用,所以存在的问题是一个线程更改这个变量后虽然同时改变了共享内存的变量,但另一线程读取这个变量时一般读的是自己的工作内存,不一定能保证实时读取到共享内存中改变后的值。 当volatile修饰后,将保证一个线程修改变量后,另一个线程实时可读被改变后的值
2.禁止指令重排序
单例模式为例:
new一个对象的三步: 1.给这个对象申请内存,会有一个默认值,比如整型默认为0 2.初始化 3.将实例指向内存,即赋值 指令重排序带来的问题: 可能在指令2(步骤2)还未执行时,先执行了指令3(步骤3),那最终得到的值将会是默认值0 volatile修饰后解决的问题: 禁止指令重排序,一定会保证初始化完成后才会赋值给实例对象
面试题:
问:单例模式中需要使用volatile关键字吗? 答案:需要,原因就是可能会有指令重排序问题,一般在超高并发下才会出现该问题
三:volatile不能代替synchronized
volatile只能保证线程的可见性(即多个线程可实时读),不能保证变量的原子性 例:
int count = 0;
count++;
即多个线程虽然可以实时读到一个线程++后的count值1,但多个线程都++成2了,结果是多个线程++后还是2
|