单例模式
因为之前研究Java比较多,所以当我试着使用go来实现一些设计模式的时候,首先想到的就是照搬Java中的思路,后面对go了解加深之后又增加了一些新的思路。
在Java中实现的单例模式的思路有很多,但是比较好的两个思路是利用类加载机制生成单例对象
,check-lock-check机制避免并发问题
我们给出这两个思路的Java代码,
利用类加载机制初始化类的静态变量,在类加载过程中的初始化阶段,会执行程序员编写的赋值语句和静态代码块,生成一个单例对象,并且这个生成过程只会执行一次,保证只生成一个单例对象。
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
check-lock-check机制,又被称为双检锁机制,第一次检查,如果已经生成了单例,就直接返回这个对象,如果还未生成单例对象,先上锁,避免多个线程去创建单例对象,再一次检查,是因为当有多个线程进入了第一次检查,我们只允许第一个进入锁的线程创建对象,其他线程都不要再创建对象。(此外volatile是为了让创建对象过程中严格遵守:分配内存,初始化,赋值引用的顺序,这里不再详细介绍,具体内容见另一篇文章,Java与设计模式)
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
我们可以直接照猫画虎吗?显然第一种方法是不可以,没有办法利用类加载机制。
来看第二种方法,我们使用了Mutex进行了加锁操作。
type singleton struct{}
var instance *singleton
var mu sync.Mutex
func GetSingleton() *singleton {
if instance == nil {
mu.Lock()
defer mu.Unlock()
if instance == nil {
instance = &singleton{}
}
}
return instance
}
此外,Go 语言在 sync 包中提供了 Once 机制能够帮助我们写出更加优雅的代码,Once 是一个结构体,在执行 Do 方法的内部通过 atomic 操作和加锁机制来保证并发安全,且 once.Do 能够保证多个 goroutine 同时执行时 &singleton{} 只被创建一次
。
package singleton
import "sync"
type singleton struct{}
var instance *singleton
var once sync.Once
func GetSingleton() *singleton {
once.Do(func() {
instance = &singleton{}
})
return instance
}
标签:singleton,Java,Singleton,Golang,instance,单例,设计模式
From: https://www.cnblogs.com/DCFV/p/18254768