go语言设计模式之单例模式
单例模式
单例模式,是一种常用的软件设计模式,在他的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例且该是例易于外界访问,从而方便对实例个数的控制并节约系统资源。
懒汉模式
懒汉模式是开源项目中使用最多的一种,最大的缺点是分线程安全的。
//懒汉模式
type singleton struct {
}
var instance *singleton
func GerInstance() *singleton {
if instance == nil {
instance = &singleton{}
}
return instance
}
带锁的单例模式
这里使用了go的sync.Mutex,其工作模式类似于Linux内核的futex对象,具体实现极其简单,性能也有保证初始化是填入的0值将mutex设定在为锁定状态,同时保证时间开销最小,这一特性允许将mutex作为其他对象的子对象使用。
//带锁的单例模式
type singleton struct {
}
var instance *singleton
var mu sync.Mutex
func GerInstance2() *singleton {
mu.Lock()
defer mu.Unlock()
if instance == nil {
instance = &singleton{}
}
return instance
}
带检查锁的单例模式
//带锁的单例模式
type singleton struct {
}
var instance *singleton
var mu sync.Mutex
func GerInstance() *singleton {
if instance == nil {
mu.Lock()
defer mu.Unlock()
if instance == nil {
instance = &singleton{}
}
}
return instance
}
这是一个不错的方法,但是还并不是很完美。因为编译器优化没有检查实例存储状态。如果使用sync.atomic包的话就可以自动帮助我们加载和设置标记。
var initialized uint32
type singleton struct {
}
var instance *singleton
var mu sync.Mutex
func GerInstance() *singleton {
if atomic.LoadUInt32(&initialized) == 1 {
return instance
}
mu.Lock()
defer mu.Unlock()
if initialized == 0 {
instance = &singleton{}
atomic.StoreUint32(&initialized,1)
}
return instance
}
比较好的一种方式sync.Once
//比较好的一种方式sync.Once
type singleton struct {
}
var instance *singleton
var once sync.Once
func GetInstance() *singleton {
once.Do(func() {
instance = &singleton{}
})
return instance
}