Lazy Loading
懒汉模式是开源项目中使用最多的一种,最大的缺点是非线程安全的
package main
import (
"fmt"
"unsafe"
)
type singleton struct {
}
var instance *singleton
func 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 main
import (
"fmt"
"sync"
"unsafe"
)
type singleton struct {
}
var instance *singleton
var lock sync.Mutex
func 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 main
import (
"fmt"
"sync"
"unsafe"
)
type singleton struct {
}
var instance *singleton
var lock sync.Mutex
func 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 *singleton
var initialized uint32
var lock sync.Mutex
func 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 main
import (
"fmt"
"sync"
"unsafe"
)
type singleton struct {
}
var instance *singleton
var once sync.Once
func 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))
}