面试题答案
一键面试sync.Once适用场景
- 单例模式:在Go语言中实现单例模式,确保某个实例只被创建一次。
- 资源初始化:对于一些需要初始化且只初始化一次的资源,如数据库连接池、配置文件加载等,使用
sync.Once
可以保证初始化的唯一性。
确保初始化安全性的原理
sync.Once
内部包含一个done
标志位和一个互斥锁mu
。第一次调用Do
方法时,done
为0,互斥锁会被锁定,执行传入的函数f
,执行完毕后将done
置为1。后续再次调用Do
方法时,由于done
已经为1,不会再执行f
,从而保证了初始化的安全性。
代码示例
package main
import (
"fmt"
"sync"
)
type Singleton struct {
data string
}
var instance *Singleton
var once sync.Once
func GetInstance() *Singleton {
once.Do(func() {
instance = &Singleton{
data: "Initial data",
}
})
return instance
}
func main() {
var wg sync.WaitGroup
var instances []*Singleton
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
inst := GetInstance()
instances = append(instances, inst)
}()
}
wg.Wait()
for i, inst := range instances {
fmt.Printf("Instance %d: %p\n", i, inst)
}
}
在上述代码中,GetInstance
函数使用sync.Once
确保instance
只被初始化一次。即使多个goroutine同时调用GetInstance
,也只会创建一个Singleton
实例。通过打印实例的地址可以验证这一点。