一、Go语言惯用的单例模式
使用sync包下once对象提供的Do方法,只执行一次
源码如下:
type Once struct {
done uint32 //标识是否做完,做完是1
m Mutex //锁
}
//通过原子操作判断o.done,如果o.done==0则f未被执行完,进入doSlow(f func()),如果f执行完则退出Do()。
func (o *Once) Do(f func()) {
if atomic.LoadUint32(&o.done) == 0 {
o.doSlow(f)
}}
//通过加锁的方式,执行`f`,并在`f`执行结束时,将`o.done`置为1
func (o *Once) doSlow(f func()) {
o.m.Lock()
defer o.m.Unlock()
if o.done == 0 {
defer atomic.StoreUint32(&o.done, 1)
f()
}
}
once详细解读:sync.once详解
实现方法:
package singleton
import (
"sync"
)
type singleton struct {}
var instance *singleton
var once sync.Once
func GetInstance() *singleton {
once.Do(func() {
instance = &singleton{}
})
return instance
}
二、原子类加锁
import "sync"
import "sync/atomic"
var initialized uint32
... // 此处省略
func GetInstance() *singleton {
if atomic.LoadUInt32(&initialized) == 1 { // 原子操作
return instance
}
mu.Lock()
defer mu.Unlock()
if initialized == 0 {
instance = &singleton{}
atomic.StoreUint32(&initialized, 1)
}
return instance
}
三、直接上重锁
var mu Sync.Mutex
type singleton struct
var instance *singleton
func GetInstance() *singleton {
mu.Lock() // 如果实例存在没有必要加锁
defer mu.Unlock()
if instance == nil {
instance = &singleton{}
}
return instance
}