在 go 中延迟互斥锁解锁时,您会遇到数据竞争吗?
Can you get a data race when deferring a mutex unlock in go?
此 Get 方法是否存在错误并且容易出现理论上的数据争用?
type item struct {
val int
mutex sync.RWMutex
}
func (i *item) Set(val int) {
i.mutex.Lock()
defer i.mutex.Unlock()
i.val = val
}
func (i *item) Get() int {
i.mutex.RLock()
defer i.mutex.RUnlock()
return i.val
}
我问是因为 运行 我用 -race
测试以前的代码时,我看到了罕见的数据竞争,但找不到任何方法来复制效果。
是否可以将 i.val 设置为不同的值,在 defer 执行 RUnlock 时和我们从结构中读取 return 值时?
Get() 必须是这样的吗?:
func (i *item) Get() int {
i.mutex.RLock()
defer i.mutex.RUnlock()
val := i.val
return val
}
您的代码是安全的,延迟函数在 return
语句的表达式列表被求值后执行。如果你有 named result parameters,return 值也会在调用延迟函数之前分配给它们(你甚至可以在 "truly" [=18] 之前修改 return 值=]从封闭函数中调用)。
无需创建局部变量来存储i.val
。
此 Get 方法是否存在错误并且容易出现理论上的数据争用?
type item struct {
val int
mutex sync.RWMutex
}
func (i *item) Set(val int) {
i.mutex.Lock()
defer i.mutex.Unlock()
i.val = val
}
func (i *item) Get() int {
i.mutex.RLock()
defer i.mutex.RUnlock()
return i.val
}
我问是因为 运行 我用 -race
测试以前的代码时,我看到了罕见的数据竞争,但找不到任何方法来复制效果。
是否可以将 i.val 设置为不同的值,在 defer 执行 RUnlock 时和我们从结构中读取 return 值时?
Get() 必须是这样的吗?:
func (i *item) Get() int {
i.mutex.RLock()
defer i.mutex.RUnlock()
val := i.val
return val
}
您的代码是安全的,延迟函数在 return
语句的表达式列表被求值后执行。如果你有 named result parameters,return 值也会在调用延迟函数之前分配给它们(你甚至可以在 "truly" [=18] 之前修改 return 值=]从封闭函数中调用)。
无需创建局部变量来存储i.val
。