单例模式:
1.饿汉模式:急于创建实例
针对唯一实例的初始化比较着急,类加载阶段就会创建实例(程序中用到了类就会立即加载)
2.懒汉模式:在用的时候才创建单例
类对象:就是.class文件被JVM加载到内存之后表现出的模样,有.class的一切信息
保证懒汉模式下的线程安全:加锁!
使用类对象作为锁对象,因为类对象在一个程序中只有唯一一份,能保证多个线程调用getInstance的时候是针对同一个对象进行的
但是每次调用getInstance都要加锁,也就可能产生锁的竞争;没有必要的竞争。
改进方案:让getInstance初始化之前才加锁,初始化之后就不加锁了。
上面的if判定是否要加锁,下面的if判定是否要创建实例。内存可见性可能会引起第一个if判定失效,但对于第二个if影响不大。
完全体的线程单例模式:
1.正确的位置加锁
2.双重ifpanding
3.volatile
class Singleton{
//1.不是立即初始化实例
public static volatile Singleton instance =null;
//2.防止程序员在其他地方不下心new,把构造方法设为private
private Singleton(){}
//3.只有真正需要用到实例的时候,才会创建实例
public static Singleton getInstance(){
//如果条件成立,说明当前的单例未初始化,存在线程安全风险,就需要加锁
if (instance==null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}