Lazy Loading

懒汉模式是开源项目中使用最多的一种,最大的缺点是非线程安全的

  1. package main
  2. import (
  3. "fmt"
  4. "unsafe"
  5. )
  6. type singleton struct {
  7. }
  8. var instance *singleton
  9. func GetInstance()*singleton{
  10. if instance ==nil {
  11. instance = &singleton{}
  12. }
  13. return instance
  14. }
  15. func main() {
  16. a := GetInstance()
  17. b := GetInstance()
  18. fmt.Println(unsafe.Pointer(a))
  19. fmt.Println(unsafe.Pointer(b))
  20. }

sync.Mutex

  1. package main
  2. import (
  3. "fmt"
  4. "sync"
  5. "unsafe"
  6. )
  7. type singleton struct {
  8. }
  9. var instance *singleton
  10. var lock sync.Mutex
  11. func GetInstance()*singleton{
  12. lock.Lock()
  13. defer lock.Unlock()
  14. if instance ==nil {
  15. instance = &singleton{}
  16. }
  17. return instance
  18. }
  19. func main() {
  20. a := GetInstance()
  21. b := GetInstance()
  22. fmt.Println(unsafe.Pointer(a))
  23. fmt.Println(unsafe.Pointer(b))
  24. }

双检查

  1. package main
  2. import (
  3. "fmt"
  4. "sync"
  5. "unsafe"
  6. )
  7. type singleton struct {
  8. }
  9. var instance *singleton
  10. var lock sync.Mutex
  11. func GetInstance()*singleton{
  12. if instance ==nil {
  13. lock.Lock()
  14. defer lock.Unlock()
  15. if instance ==nil {
  16. instance = &singleton{}
  17. }
  18. }
  19. return instance
  20. }
  21. func main() {
  22. a := GetInstance()
  23. b := GetInstance()
  24. fmt.Println(unsafe.Pointer(a))
  25. fmt.Println(unsafe.Pointer(b))
  26. }

sync/atomic

因为编译器优化没有检查实例存储状态。如果使用sync/atomic包的话 就可以自动帮我们加载和设置标记。

  1. type singleton struct {
  2. }
  3. var instance *singleton
  4. var initialized uint32
  5. var lock sync.Mutex
  6. func GetInstance()*singleton{
  7. if atomic.LoadUint32(&initialized)==1 {
  8. return instance
  9. }
  10. lock.Lock()
  11. defer lock.Unlock()
  12. if initialized == 0{
  13. instance = &singleton{}
  14. atomic.StoreUint32(&initialized,1)
  15. }
  16. return instance
  17. }

sync.Once

  1. package main
  2. import (
  3. "fmt"
  4. "sync"
  5. "unsafe"
  6. )
  7. type singleton struct {
  8. }
  9. var instance *singleton
  10. var once sync.Once
  11. func GetInstance()*singleton{
  12. once.Do(func() {
  13. instance = &singleton{}
  14. })
  15. return instance
  16. }
  17. func main() {
  18. a := GetInstance()
  19. b := GetInstance()
  20. fmt.Println(unsafe.Pointer(a))
  21. fmt.Println(unsafe.Pointer(b))
  22. }