美文网首页程序员
设计模式之单例模式

设计模式之单例模式

作者: 进步源于积累 | 来源:发表于2018-09-30 14:58 被阅读0次

是什么?

单例指一个类确保只有一个实例。就加载出一个,谁都用这一个。

实现方式

饿汉式-饿了,早点吃。类加载时就实例化。

实现方式就下面这样:

public class Singleton {

private static Singleton uniqueInstance = new Singleton();

private Singleton() { }

public static Singleton getUniqueInstance() {

    return uniqueInstance;

}

}

懒汉式-为啥说它懒呢,是这样的,你要的时候它才造一个给你,延迟加载的。你不要,就不会实例化,有点好处就是省资源。

实现方式就下面这样:

public class Singleton {

private static Singleton uniqueInstance;

private Singleton() {

}

public static Singleton getUniqueInstance() {

if (uniqueInstance == null) {

    uniqueInstance = new Singleton();

}

    return uniqueInstance;

}

}

问题来了

线程安全吗?这么简单就能线程安全,怎么也得多写一点。

好,给方法加锁。改进一下。

public static synchronized Singleton getUniqueInstance() {

if (uniqueInstance == null) {

    uniqueInstance = new Singleton();

}

    return uniqueInstance;

}

当一个线程进入该方法之后,其它试图进入该方法的线程都必须等待,即使 uniqueInstance 已经被实例化了。这会让线程阻塞时间过长,因此该方法有性能问题,不推荐使用。

那么再想一个办法,缩小加锁的范围。

public class Singleton {

private volatile static Singleton uniqueInstance;

private Singleton() {

}

public static Singleton getUniqueInstance() {

if (uniqueInstance == null) {

    synchronized (Singleton.class) {

if (uniqueInstance == null) {

    uniqueInstance = new Singleton();

} } }

    return uniqueInstance;

}}

双重校验锁先判断 uniqueInstance 是否已经被实例化,如果没有被实例化,那么才对实例化语句进行加锁。

uniqueInstance = new Singleton(); 这段代码其实是分为三步执行:

1.为 uniqueInstance 分配内存空间

2.初始化 uniqueInstance

3.将 uniqueInstance 指向分配的内存地址

理论是这样,实际上,多线程的时候,这个就不一定按这个顺序了。

volatile的作用就来了。加上这个volatile禁止JVM重排序,就按上面这个进行了。

ok,大概就这么回事。

参考地址:CS-Notes  这个写真的很Nice

相关文章

网友评论

    本文标题:设计模式之单例模式

    本文链接:https://www.haomeiwen.com/subject/tsjwoftx.html