我有一段代码,它对对象的初始化进行了双重检查锁定。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() }}这段代码在mutex.RLock()第一次 nil 检查之前。为什么需要这样?(它在页面中有解释,但我无法理解)并且它不会增加开销,因为每次调用 checkSyncProducer 时都会获取和释放读取锁。在获取读锁之前是否应该再进行一次 nil 检查,例如: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 不会被不必要地占用。我对么?
2 回答
慕标5832272
TA贡献1966条经验 获得超4个赞
如果你没有获取 RLock 来读取syncProducer,那就是数据竞争,因为另一个 goroutine 可能会更新它。
如果你假设对指针变量的读/写是原子的,这看起来是无害的——活泼的读syncProducer永远不会导致不正确的行为。如果你不做这个原子假设,如果你不走运的话,读取可能只产生指针的一些字节,你的程序就会崩溃。
根据您使用的体系结构、机器字长、编译器版本等,这可能会也可能不会。但这RLock避免了任何担忧。
与其显式地乱用 RWLocks,不如使用它(假设目标是懒惰地初始化一个变量):
var (
syncOnce sync.Once
syncProducerInternal *syncProducerType
)
func syncProducer() *syncProducerType {
syncOnce.Do(func() { syncProducerInternal = createSyncKafkaProducer() })
return syncProducerInternal
}
然后需要同步生产者的代码可以调用该syncProducer()函数来获取它,而永远不会看到 nil 指针。
- 2 回答
- 0 关注
- 143 浏览
添加回答
举报
0/150
提交
取消