/** * @Description: * @Package: lsr-microservice * @author: Hacker_lsr@126.com **/ public class VolatileTest { int x = 0 ; volatile boolean v = false; public void writer(){ x = 42 ; v = true; } public void reader(){ if (v = true){ // x = ? ; x = ? } } }
例如下面的示例代码,假设线程 A 执行 writer() 方法,按照 volatile 语义,会把变量 “v=true” 写入内存;假设线程 B 执行 reader() 方法,同样按照 volatile 语义,线程 B 会从内存中读取变量 v,如果线程 B 看到 “v == true” 时,那么线程 B 看到的变量 x 是 多少呢?
直觉上看,应该是 42,那实际应该是多少呢?这个要看 Java 的版本,如果在低于 1.5 版 本上运行,x 可能是 42,也有可能是 0;如果在 1.5 以上的版本上运行,x 就是等于 42。
/** * @Description: * @Package: lsr-microservice * @author: Hacker_lsr@126.com **/ public class Instance { private static volatile Instance instance; public Instance(){} public static Instance getInstance(){ if (instance==null){ synchronized (Instance.class){ // 1 if (instance==null){// 2 instance = new Instance();// 3 } } } return instance; } }
执行过程:
双重校验锁方式的执行过程如下:
1.线程A进入 getInstance() 方法。
2.由于 instance为 null,线程A在 //1 处进入 synchronized 块。
3.线程A被线程B预占。
4.线程B进入 getInstance() 方法。
5.由于 instance仍旧为 null,线程B试图获取 //1 处的锁。然而,由于线程A已经持有该锁,线程B在 //1 处阻塞。
6.线程B被线程A预占。
7.线程A执行,由于在 //2 处实例仍旧为 null,线程A还创建一个 instance 对象并将其引用赋值给 instance。
8.线程A退出 synchronized 块并从 getInstance() 方法返回实例。
9.线程A被线程B预占。
10.线程B获取 //1 处的锁并检查 instance 是否为 null。
11.由于 instance是非 null 的,并没有创建第二个 Instance 对象,由线程A所创建的对象被返回。