Skip to content

Latest commit

 

History

History
99 lines (68 loc) · 1.91 KB

单例模式.md

File metadata and controls

99 lines (68 loc) · 1.91 KB

单例模式

饿汉式

初始阶段就完成对象的实例化,并保持一种饥饿渴求的状态。无论此单例是否有人使用。

缺点:没人用就占用内存。

public class Sun {

    private static final Sun sun = new Sun();

    private Sun() {

    }

    public Sun getInstance() {
        return sun;
    }
}

懒汉式

解决饿汉式有可能造成内存浪费的问题。

public class Sun {

    private static Sun sun;

    private Sun() {

    }

    public static Sun getInstance() {
        if (sun == null) {	//有可能多个线程逻辑判断同时成立
            sun = new Sun();
        }
        return sun;
    }
}

懒汉式在第一次获取对象时比饿汉式要慢。

并且有线程安全问题。

线程安全的懒汉式

public class Sun {

    private static Sun sun;

    private Sun() {

    }
    
    //加上了同步锁,所有线程一个一个获取实例
    public static synchronized Sun getInstance() {	
        if (sun == null) {
            sun = new Sun();
        }
        return sun;
    }
}

上述加锁的范围很大,锁有点重。

优化线程安全的懒汉式

public class Sun {

    // volatile防止指令重排序
    private volatile static Sun sun;

    private Sun() {

    }

    public static Sun getInstance() {
        if (sun == null) {
            synchronized (Sun.class){
                if(sun==null){	// 避免多次创建对象
                    sun = new Sun();
                }
            }
        }
        return sun;
    }
}
  • 如果对象已经创建了,后面再次调用直接返回单例对象即可。
  • sun = new Sun ();可以分解为:分配内存、初始化对象、指向分配内存地址三个步骤。有可能重排序为分配内存、指向分配内存地址,最后初始化对象。那么其它线程可能获取到一个未初始化的对象。