以下无锁代码是否表现出竞争条件?

时间:2016-12-23 01:34:45

标签: multithreading go lock-free compare-and-swap

Kubernetes Go repo on Github.com内,

HighWaterMark数据结构的无锁实现。此代码依赖于原子操作来实现没有数据争用的线程安全代码。

// HighWaterMark is a thread-safe object for tracking the maximum value seen
// for some quantity.
type HighWaterMark int64

// Update returns true if and only if 'current' is the highest value ever seen.
func (hwm *HighWaterMark) Update(current int64) bool {
    for {
        old := atomic.LoadInt64((*int64)(hwm))
        if current <= old {
            return false
        }
        if atomic.CompareAndSwapInt64((*int64)(hwm), old, current) {
            return true
        }
    }
}

此代码依赖于标准库中的atomic.LoadInt64atomic.CompareAndSwapInt64函数来实现数据竞争免费代码......我相信它确实存在,但我相信存在竞争条件的另一个问题。

如果两个竞争线程(goroutines)正在执行此类代码,则存在边缘情况,其中在第一个线程中发生atomic.LoadInt64之后,第二个线程可能已换出更高的值。但是在第一个线程认为后,current int64实际上大于old int64,就会发生交换。然后,由于观察到陈旧的old值,此交换将有效地降低存储值。

1 个答案:

答案 0 :(得分:1)

如果另一个线程进入中间,则CompareAndSwap将失败并且循环将重新开始。

将CompareAndSwap视为

if actual == expected { 
   actual = newval
}

但原子地完成

所以这段代码说:

old = hwm // but done in a thread safe atomic read way
if old < current {
   set hwm to current if hwm == old // atomically compare and then set value
}

当CAS(CompareAndSwap)失败时,它返回false,导致循环重新开始,直到:

a)&#34;当前&#34;不大于hwm

b)它成功执行Load,然后是CompareAndSwap而中间没有另一个线程