一、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
}