GoLang 常见设计模式之: 单例模式
双重锁定(Double-Check Locking)
1package singleton
2
3import "sync"
4
5type singleton struct{}
6
7var instance *singleton
8var mu sync.Mutex
9
10func GetSingleton() *singleton {
11 if instance == nil {
12 mu.Lock()
13 defer mu.Unlock()
14 if instance == nil {
15 instance = &singleton{}
16 }
17 }
18 return instance
19}
外层 instance == nil 判断免去原来每次调用 GetSingleton () 都上锁,提高程序的执行效率。内层 instance == nil 判断则考虑了并发安全,在极端情况下多个 goroutine 同时走到加锁这一步,内层判断会在这里起到作用。
标准方案
1package singleton
2
3import "sync"
4
5type singleton struct{}
6
7var instance *singleton
8var once sync.Once
9
10func GetSingleton() *singleton {
11 once.Do(func() {
12 instance = &singleton{}
13 })
14 return instance
15}
Once 是一个结构体,在执行 Do 方法的内部通过原子(atomic)操作和加锁机制来保证并发安全,且 once.Do 能够保证多个 goroutine 同时执行时 &singleton {} 只被创建一次。