package com.zll;
public class Single {
//volatile 必须要加,防止指令重排序,在百万级并非量时,可能会出现问题。虽然很小,但是要知道这是完美写法。
//例如初始化对象 Integer 100:
// 1、首先初始化Integer对象并设置默认值0。
// 2、在将初始化对象的值设置成初始值100。
// 3、最后将引用的值赋值给引用对象。
//在现在多核cpu,会有一个指令重排序的优化。指令重排序是指:在不影响结果的情况下,可能会先执行1、后直接指向3,然后在指向2.
//可能就会出现的结果就是,先执行了第3步,后来的线程发现对象有值了,直接将0++,这个时候 再执行第2步时,对象再次被赋值成 100,导致,第一个++操作丢失。
private static volatile Single INSTANCE;
public synchronized static Single getInstance(){
if(INSTANCE == null){
INSTANCE = new Single();
}
return INSTANCE;
}
private Single() {}
public static void main(String[] args) {
for (int i=0; i<100; i++){
new Thread(()->{
System.out.println(Single.getInstance().hashCode());
}).start();
}
}
}
public class TestJVM {
public static void main(String[] args) {
System.out.println(T.count); //答案是3
}
}
//静态类成员的执行顺序是由上直下的
//首先在内存中 T 的 count被初始化为0
//然后开始执行static 对象赋值操作 count = 2
//最后在执行 static T t = new T();
//构造放啊count ++ 于是 count = 3
class T{
public static int count = 2;
public static T t = new T();
public T() {
count ++;
}
}