第一个版本:单线程下是线程安全:
package main
import "fmt"
var instance *Singleton
type Singleton struct {
Name string
}
// 非线程安全版本Singleton
func GetInstance() *Singleton{
if instance == nil{
instance = &Singleton{}
return instance
}
return instance
}
func main(){
s1 := GetInstance()
fmt.Printf("s1 指针是%p \n",s1)
s2 := GetInstance()
fmt.Printf("s2 指针是%p \n",s2)
}
从结果中可以看出单线程下是安全
s1 指针是0xc00004e1c0
s2 指针是0xc00004e1c0
第二个版本 多线程 :
package main
import (
"fmt"
"time"
)
var instance *Singleton
type Singleton struct {
Name string
}
// 非线程安全版本Singleton
func GetInstance() *Singleton{
if instance == nil{
fmt.Println("---------------")
instance = &Singleton{}
return instance
}
return instance
}
func main(){
for i := 0 ;i <5 ;i ++ {
go func(i int) {
s := GetInstance()
fmt.Printf("i= %d, s = %p\n", i, s)
}(i)
}
time.Sleep(time.Second)
}
从运行的结果中可以看出, 在多线程下不安全的
---------------
---------------
i= 1, s = 0xc0000c6000
---------------
i= 4, s = 0xc0000c6020
i= 0, s = 0xc000040010
---------------
i= 3, s = 0xc00004e1c0
---------------
i= 2, s = 0xc00004e1e0
第三个版本,使用mutex锁机制:
package main
import (
"fmt"
"sync"
"time"
)
var instance *Singleton
var mu sync.Mutex
type Singleton struct {
Name string
}
// 非线程安全版本Singleton
func GetInstance() *Singleton{
mu.Lock()
defer mu.Unlock()
if instance == nil{
fmt.Println("---------------")
instance = &Singleton{}
return instance
}
return instance
}
func main(){
for i := 0 ;i <5 ;i ++ {
go func(i int) {
s := GetInstance()
fmt.Printf("i= %d, s = %p\n", i, s)
}(i)
}
time.Sleep(time.Second)
}
从运行的结果中可以看出, 在多线程下运行是线程安全的,但是由于锁的机制,运行的效率不高。
---------------
i= 2, s = 0xc000040010
i= 4, s = 0xc000040010
i= 0, s = 0xc000040010
i= 1, s = 0xc000040010
i= 3, s = 0xc000040010
第四个版本 使用 sync.Once 初始化
package main
import (
"fmt"
"sync"
"time"
)
var instance *Singleton
var once sync.Once
type Singleton struct {
Name string
}
// 线程安全版本Singleton
func GetInstance() *Singleton{
once.Do(
func() {
if instance == nil{
fmt.Println("---------------")
instance = &Singleton{}
}
})
return instance
}
func main(){
for i := 0 ;i <5 ;i ++ {
go func(i int) {
s := GetInstance()
fmt.Printf("i= %d, s = %p\n", i, s)
}(i)
}
time.Sleep(time.Second)
}
从运行的结果看,是一个线程安全
i= 0, s = 0xc000040010
i= 1, s = 0xc000040010
i= 3, s = 0xc000040010
i= 4, s = 0xc000040010
i= 2, s = 0xc000040010