gpt4 book ai didi

go - 双重检查 golang 中的锁定 - 为什么需要 mutex.RLock()?

转载 作者:IT王子 更新时间:2023-10-29 02:26:08 26 4
gpt4 key购买 nike

我有一段来自 this website 的代码它对对象的初始化进行了双重检查锁定。

func checkSyncProducer() {
mutex.RLock()
if syncProducer == nil {
mutex.RUnlock()
mutex.Lock()
defer mutex.Unlock()
if syncProducer == nil {
syncProducer = createSyncKafkaProducer() //this func will initialize syncProducer.
}
} else {
defer mutex.RUnlock()
}
}

这段代码在第一次 nil 检查之前有 mutex.RLock()

为什么需要这样做? (它在页面中有解释,但我无法理解)并且它不会增加开销,因为每次调用 checkSyncProducer 时都会获取和释放读取锁。

在获取读锁之前是否应该再进行一次零检查,例如:

func checkSyncProducer() {
if syncProducer == nil {
mutex.RLock()
if syncProducer == nil {
mutex.RUnlock()
mutex.Lock()
defer mutex.Unlock()
if syncProducer == nil {
createSyncKafkaProducer()
}
} else {
defer mutex.RUnlock()
}
}
}

第一个 nil 检查将确保 RLock 不会被不必要地占用。我对么?

最佳答案

如果您没有获取 RLock 来读取 syncProducer,这是一场数据竞争,因为另一个 goroutine 可能会更新它。

如果您假设对指针变量的读/写是原子的,这看起来是无害的——syncProducer 的快速读取永远不会导致不正确的行为。如果您不进行这种原子假设,那么如果您不走运,读取操作可能只会产生指针的一些字节,您的程序就会崩溃。

根据您使用的体系结构、机器字长、编译器版本等,它可能可行也可能不可行。但是 RLock 避免了任何问题。

与其显式地乱用 RWLocks,不如使用它(假设目标是延迟初始化变量):

var (
syncOnce sync.Once
syncProducerInternal *syncProducerType
)

func syncProducer() *syncProducerType {
syncOnce.Do(func() { syncProducerInternal = createSyncKafkaProducer() })
return syncProducerInternal
}

然后需要同步生产者的代码可以调用 syncProducer() 函数来获取它,并且永远不会看到 nil 指针。

关于go - 双重检查 golang 中的锁定 - 为什么需要 mutex.RLock()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54092981/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com