GoLang 常见设计模式之: 单例模式

1 minute read

双重锁定(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 {} 只被创建一次。