设计模式-单例模式
2011 年 6 月 28 日
单例模式可以说是最容易理解的一种设计模式了,当需要某个类仅有一个全局唯一对象时可以使用,比如某些配置项。核心思想就是新建某个类实例时先进行一次判断,如果不存在则创建新实例返回,否则返回已经存在的实例。
懒汉模式(Lazy Loading)
很常见的一种方式,不过并非是线程安全的:
type singleton struct { } var instance *singleton func GetInstance() *singleton { if instance == nil { instance = &singleton{} } return instance }
带单锁的单例模式
import "sync" type singleton struct { } var instance *singleton var mu sync.Mutex func GetInstance() *singleton { mu.Lock() defer mu.Unlock() if instance == nil { instance = &singleton{} } return instance }
解决线程安全问题,很容易想到的就是加锁。这种方式有个缺点就是每次获取实例时候都要对锁进行操作,会降低性能。
双重锁定
package main import ( "fmt" "sync" "sync/atomic" ) type singleton struct { } var instance *singleton var mu sync.Mutex var initialized uint32 func GetInstance() *singleton { if atomic.LoadUint32(&initialized) == 1 { return instance } mu.Lock() defer mu.Unlock() if instance == nil { instance = &singleton{} atomic.StoreUint32(&initialized, 1) } return instance }
这里使用 atomic
来保证原子操作。不过代码还可以更精简,使用golang中的 Once
:
import ( "fmt" "sync" ) type singleton struct { } var instance *singleton var once sync.Once func GetInstance() *singleton { once.Do(func() { instance = &singleton{} }) return instance }