volatile 可以防止,指令重拍,这个大多数小伙伴是知道的,但是他防止的是哪些指令的重拍呢?如果我们放任指令重拍会产生什么严重后果呢?这个未必都知道,下面就把这个问题说清楚。
1.1 源码
package com.yuhl.c2020;
/**
* @author yuhl
* @Date 2020/12/30 20:25
* @Classname Chongpai
* @Description 指令重拍
*/
public class Chongpai {
public static void main(String[] args) {
Object o = new Object();
}
}
1.2 指令码
0 new #2 <java/lang/Object>
3 dup
4 invokespecial #1 <java/lang/Object.<init>>
7 astore_1
8 return
1.3 指令码解释
- 从上面的解释可看到 1,2,3 这散步是一步一步来的,但是在 jvm 的底层,2,3 步可能是乱序的,也就是说可能真正的过程是 1,3,2 或者是 1,2,3
- 如果是 1,2,3 应该不会出现什么问题,如果是 1,3,2 那么就可能会出大问题,出什么问题呢?
2.1 双重检查单例的代码实现
package com.yuhl.c2020;
/**
* @author yuhl
* @Date 2020/12/30 20:44
* @Classname SinDobleCheck
* @Description 单例模式,双重检查,特别关注volatile
*/
public class SinDobleCheck {
private static int count = 100;
private static volatile SinDobleCheck INSTANCE; //JIT
private SinDobleCheck() {
}
public static SinDobleCheck getInstance() {
if (INSTANCE == null) {
//双重检查
synchronized (SinDobleCheck.class) {
if(INSTANCE == null) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
INSTANCE = new SinDobleCheck();
}
}
}
return INSTANCE;
}
public void m() {
System.out.println("m");
}
public static void main(String[] args) {
for(int i=0; i<100; i++) {
new Thread(()->{
System.out.println(SinDobleCheck.getInstance().hashCode());
}).start();
}
}
}
2.2 如果不用 volatile 问题在哪里
- 通过图中 7 点可以看出不实用 volatile 会出现的问题。
- 如果使用了 volatile 就会防止指令重拍,那么执行的顺序一定是 1,2,3,4,7,5,6 这样就是安全的。
在多线程中 volatile 尤其重要,在写代码的时候需要特别关注!
自律的艰辛总甜过懊悔的苦果!
专注于 java 后端技术及解决方案,善于总结,分享!
自律的艰辛总甜过懊悔的苦果!
专注于 java 后端技术及解决方案,善于总结,分享!
自律的艰辛总甜过懊悔的苦果!
专注于 java 后端技术及解决方案,善于总结,分享!