作者简介: zoro-1,目前大二,正在学习Java,数据结构,javaee等
作者主页: zoro-1的主页
欢迎大家点赞 ?? 收藏 ? 加关注哦!????
volatile关键字解决的问题
- 内存可见性
- 指令重排序
内存可见性
import java.util.Scanner; public class text { static int flag=0; public static void main(String[] args) { Thread thread=new Thread(()->{ while (flag==0){ } System.out.println("任务执行完毕"); }); Thread thread1=new Thread(()->{ System.out.println("请输入flag的值"); Scanner scanner=new Scanner(System.in); flag= scanner.nextInt(); }); thread.start(); thread1.start(); } }
上面的代码执行后是这样的:
但根据逻辑应该是当thread1线程执行到等待用户输出flag值时若flag为非0数子,thread线程内的whlie循环结束输出任务执行完毕,由代码执行结果可知以上代码存在bug那是什么原因导致的呢?
将flag==0的指令原子化就得到一下两条指令:
1.load读取内存中flag的值到cpu寄存器中(cpu开销大)
2.拿着cpu寄存器中的flag的值和0进行比较(cpu开销小)
而在线程thread1等待io的几秒中线程thread疯狂执行,而1指令的开销过大jvm就会将1操作优化掉只剩下2操作,执行速度虽然大大提高,但会存在bug,就是在用户输出非零数字也不会执行1操作就导致无法结束thread线程
import java.util.Scanner; public class text { static volatile int flag=0; public static void main(String[] args) { Thread thread=new Thread(()->{ while (flag==0){ } System.out.println("任务执行完毕"); }); Thread thread1=new Thread(()->{ System.out.println("请输入flag的值"); Scanner scanner=new Scanner(System.in); flag= scanner.nextInt(); }); thread.start(); thread1.start(); } }
这是改完bug的代码其实就是将flag前面加上volatile,这个关键词可以取消jvm的优化,就可以顺利执行完毕
指令重排序
public class texr { public static void main(String[] args) { texr t=new texr(); } }
指令重排序就是在执行以上代码时,jvm会将它进行优化,首先将以上代码原子化:
1.申请一段内存空间
2.在这个内存上调用构造方法创建实例
3.将这个内存地址赋值给t变量
通常都是123顺序执行,而jvm有可能将以上指令优化成132执行,这样的优化在单线程执行下没问题但在多线程代码下可能就会出现问题具体例子请看。。
今天的分享到这里就结束了,感谢大家支持