我想用 Go 实现一个单例。普通单例的区别在于实例是单例,在映射结构中具有不同的键。像这样的代码。我不确定演示代码是否存在任何数据竞争。
var instanceLock sync.Mutex
var instances map[string]string
func getDemoInstance(key string) string {
if value, ok := instances[key]; ok {
return value
}
instanceLock.Lock()
defer instanceLock.Unlock()
if value, ok := instances[key]; ok {
return value
} else {
instances[key] = key + key
return key + key
}
}
最佳答案
是的,有数据竞争,你可以用 go run -race main.go
运行它来确认.如果一个 goroutine 锁定并修改了映射,则另一个 goroutine 可能会在锁定之前读取它。
您可以使用 sync.RWMutex
读取时锁定(允许多个读取器互不阻塞)。
例如:
var (
instancesMU sync.RWMutex
instances = map[string]string{}
)
func getDemoInstance(key string) string {
instancesMU.RLock()
if value, ok := instances[key]; ok {
instancesMU.RUnlock()
return value
}
instancesMU.RUnlock()
instancesMU.Lock()
defer instancesMU.Unlock()
if value, ok := instances[key]; ok {
return value
}
value := key + key
instances[key] = value
return value
}
关于go - 如何实现单例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62260512/