懒汉式的三种线程安全的写法

双重检查锁

public class Student {
	private static Student student=null;
	private Student() {
		
	}
	public static Student getSingletonInstance() {
		if (student==null) {
			synchronized (Student.class) {
				if (student==null) {
					student=new Student();
				}
			}
		}
		return student;
	}
}

静态内部类的单例写法

public class Student {
	private Student() {
		
	}
	private static class StaticStudentFactory {
		private static Student student=new Student();
	}
	public static Student getSingletonInstance() {
		return StaticStudentFactory.student;
	}
}

如何破坏单例?(导致单例对象不单例)

  • 反射攻击
  • public class SingletonAttack {
        public static void main(String[] args) throws Exception {
    	reflectionAttack();
        }
    
        public static void reflectionAttack() throws Exception {
    	//通过反射,获取单例类的私有构造器
    	Constructor constructor = DoubleCheckLockSingleton.class.getDeclaredConstructor();
            //设置私有成员的暴力破解
    	constructor.setAccessible(true);
    	// 通过反射去创建单例类的多个不同的实例
    	DoubleCheckLockSingleton s1 = (DoubleCheckLockSingleton)constructor.newInstance();
            // 通过反射去创建单例类的多个不同的实例
    	DoubleCheckLockSingleton s2 = (DoubleCheckLockSingleton)constructor.newInstance();
    	s1.tellEveryone();
    	s2.tellEveryone();
    	System.out.println(s1 == s2);
        }
    }

     

  • 序列化攻击
  • public class SingletonAttack {
        public static void main(String[] args) throws Exception {
    	serializationAttack();
        }
    
        public static void serializationAttack() throws Exception {
    	// 对象序列化流去对对象进行操作
    	ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("serFile"));
    	//通过单例代码获取一个对象
    	DoubleCheckLockSingleton s1 = DoubleCheckLockSingleton.getInstance();
    	//将单例对象,通过序列化流,序列化到文件中
    	outputStream.writeObject(s1);
    					
    	// 通过序列化流,将文件中序列化的对象信息读取到内存中
    	ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(new File("serFile")));
    	//通过序列化流,去创建对象
    	DoubleCheckLockSingleton s2 = (DoubleCheckLockSingleton)inputStream.readObject();
    	s1.tellEveryone();
    	s2.tellEveryone();
    					
    	System.out.println(s1 == s2);
        }
    }

     

枚举单例(最简单最安全)==枚举没有默认的无参构造器

  • public enum EnumSingleton {
        INSTANCE;
    
        public void tellEveryone() {
    	System.out.println("This is an EnumSingleton " + this.hashCode());
        }
    }

     

 

你可能感兴趣的:(设计模式)