在go中延迟互斥解锁时,是否会出现数据竞争?

在go中延迟互斥解锁时,是否会出现数据竞争?,go,mutex,deferred,Go,Mutex,Deferred,这种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.RUn

这种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
测试时看到了一个罕见的数据竞争,但是找不到任何复制效果的方法

在延迟执行RUnlock和从结构读取并返回值之间,i.val是否可以设置为不同的值

Get()必须是这样的吗

func (i *item) Get() int {
    i.mutex.RLock()
    defer i.mutex.RUnlock()
    val := i.val
    return val
}

您的代码是安全的,在计算
return
语句的表达式列表后执行延迟函数。如果需要,在调用延迟函数之前也会将返回值分配给它们(甚至可以在从封闭函数“真正”返回之前修改返回值)


无需创建局部变量来存储
i.val

您是否有该数据竞争的任何跟踪?几乎没有。使用RWMutex表明您关心性能,因此不要延迟解锁调用,而是直接调用它们。这对于set来说非常简单,get需要上一个解决方案的临时值。除此之外:比赛报告在哪里?以上是我实际代码的简化版本。我只是想检查一下我对延迟的理解,排除一些可能性。更仔细地检查我的种族跟踪会导致我在其他地方发现一个bug。