Lazy Loading
懒汉模式是开源项目中使用最多的一种,最大的缺点是非线程安全的
package mainimport ("fmt""unsafe")type singleton struct {}var instance *singletonfunc GetInstance()*singleton{if instance ==nil {instance = &singleton{}}return instance}func main() {a := GetInstance()b := GetInstance()fmt.Println(unsafe.Pointer(a))fmt.Println(unsafe.Pointer(b))}
sync.Mutex
package mainimport ("fmt""sync""unsafe")type singleton struct {}var instance *singletonvar lock sync.Mutexfunc GetInstance()*singleton{lock.Lock()defer lock.Unlock()if instance ==nil {instance = &singleton{}}return instance}func main() {a := GetInstance()b := GetInstance()fmt.Println(unsafe.Pointer(a))fmt.Println(unsafe.Pointer(b))}
双检查
package mainimport ("fmt""sync""unsafe")type singleton struct {}var instance *singletonvar lock sync.Mutexfunc GetInstance()*singleton{if instance ==nil {lock.Lock()defer lock.Unlock()if instance ==nil {instance = &singleton{}}}return instance}func main() {a := GetInstance()b := GetInstance()fmt.Println(unsafe.Pointer(a))fmt.Println(unsafe.Pointer(b))}
sync/atomic
因为编译器优化没有检查实例存储状态。如果使用sync/atomic包的话 就可以自动帮我们加载和设置标记。
type singleton struct {}var instance *singletonvar initialized uint32var lock sync.Mutexfunc GetInstance()*singleton{if atomic.LoadUint32(&initialized)==1 {return instance}lock.Lock()defer lock.Unlock()if initialized == 0{instance = &singleton{}atomic.StoreUint32(&initialized,1)}return instance}
sync.Once
package mainimport ("fmt""sync""unsafe")type singleton struct {}var instance *singletonvar once sync.Oncefunc GetInstance()*singleton{once.Do(func() {instance = &singleton{}})return instance}func main() {a := GetInstance()b := GetInstance()fmt.Println(unsafe.Pointer(a))fmt.Println(unsafe.Pointer(b))}
