3、指令重排(你写的程序,计算机并不会按照你写的去执行)
源代码–>编译器优化重排–>指令并行也可能会重排–>内存系统也会重排–>执行
内存屏障、cpu指令。作用:
1、保证特定的操作的执行顺序!
2、可以保证某些变量内存的可见性(利用这些特性,就可以保持)
加了volatile是可以保持可见性,不能保证原子性,由于内存屏障,可以保证避免指令 重排
18、彻底玩转单例模式
饿汉式单例模式:
package com.huang.single;
//饿汉式单例模式
public class hungry {
//浪费资源
private byte[] data1=new byte[1024*1024];
private byte[] data2=new byte[1024*1024];
private byte[] data3=new byte[1024*1024];
private byte[] data4=new byte[1024*1024];
private byte[] data5=new byte[1024*1024];
private hungry(){
System.out.println("i am hungry");
}
private final static hungry hungry =new hungry();
public static hungry getInstance(){
return hungry;
}
}
class test{
public static void main(String[] args) {
hungry.getInstance();
}
}
懒汉式单例(双重检测锁 排除构造对象是存在的指令重排问题!):
package com.huang.single;
//Dcl懒汉式单例模式
public class LazyMan {
private LazyMan(){
System.out.println(Thread.currentThread().getName()+"=>ok");
}
private volatile static LazyMan lazyMan;//加上volatile关键字避免出现指令重排现象
public static LazyMan getInstance(){
if (lazyMan==null){//双层检测加锁模式 DCL懒汉式
synchronized (LazyMan.class){
if (lazyMan==null){
lazyMan = new LazyMan();//不是一个原子性操作
/**
* 1、分配内存
* 2、执行构造方法,初始化对象
* 3、把这个对象指向这个空间
*存在指令重排问题!!!!!
* */
}
}
}
return lazyMan; //可能导致lazyman还没有构造
}
//多线程并发(存在问题--->加锁)
public static void main(String[] args) {
for (int i = 0; i <10 ; i++) {
new Thread(()->{
LazyMan.getInstance();
}).start();
}
}
}
静态内部类:
package com.huang.single;
//静态内部类
public class Hold {
private Hold(){
System.out.println("hahah");
}
public static Hold getInstance(){
return innerClass.hold;
}
public static class innerClass{
private static final Hold hold= new Hold();
}
}
class Test{
public static void main(String[] args) {
Hold.getInstance();
}
}
利用反射破坏单例模式!!!:
package com.huang.single;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
//Dcl懒汉式单例模式
public class LazyMan {
private static boolean huang = false;
private LazyMan(){
synchronized (LazyMan.class){
if (huang==false){
huang=true;
}else {
throw new RuntimeException("不要视图使用反射破坏异常!");
}
}
}
private volatile static LazyMan lazyMan;
public static LazyMan getInstance(){
if (lazyMan==null){//双层检测加锁模式 DCL懒汉式
synchronized (LazyMan.class){
if (lazyMan==null){
lazyMan = new LazyMan();//不是一个原子性操作
/**
* 1、分配内存
* 2、执行构造方法,初始化对象
* 3、把这个对象指向这个空间
*存在指令重排问题!!!!!
* */
}
}
}
return lazyMan;
}
public static void main(String[] args) throws Exception {
//反射可以破坏这种单例
// LazyMan instance = LazyMan.getInstance();
Field huang = LazyMan.class.getDeclaredField("huang");
huang.setAccessible(true);
Constructor<LazyMan> constructor = LazyMan.class.getDeclaredConstructor(null);//获取空参构造器
constructor.setAccessible(true);
LazyMan instance1 = constructor.newInstance();
huang.set(instance1,false);
LazyMan instance2 = constructor.newInstance();
System.out.println(instance2);
System.out.println(instance1);
}
}
反射无法破坏枚举(枚举构造方法中存在参数(String,int)):
package com.huang.single;
import java.lang.reflect.Constructor;
//enum 1.5jdk 本身也是一个类
public enum EnumSingle {
INSTANCE;
public EnumSingle getInstance(){
return INSTANCE;
}
}
//反射不能破坏枚举
class Test02 {
public static void main(String[] args) throws Exception {
EnumSingle instance1=EnumSingle.INSTANCE;
// Constructor<EnumSingle> declaredConstructor = EnumSingle.class.getDeclaredConstructor(null);
Constructor<EnumSingle> declaredConstructor = EnumSingle.class.getDeclaredConstructor(String.class,int.class);
declaredConstructor.setAccessible(true);
System.out.println(instance1);
EnumSingle instance2 = declaredConstructor.newInstance();
//运行结果 java.lang.NoSuchMethodException: com.huang.single.EnumSingle.<init>()
System.out.println(instance2);
}
}
nce2 = declaredConstructor.newInstance();
//运行结果 java.lang.NoSuchMethodException: com.huang.single.EnumSingle.()
System.out.println(instance2);
}
}