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

Posted

技术标签:

【中文标题】以下无锁代码是不是表现出竞争条件?【英文标题】:Does the following lock-free code exhibit a race-condition?以下无锁代码是否表现出竞争条件? 【发布时间】:2016-12-23 01:34:44 【问题描述】:

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】:

如果另一个线程进入中间,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) “当前”不大于 hwm

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

【讨论】:

啊哈!在阅读了您的答案大约 5 次后,它刚刚为我点击了。

以上是关于以下无锁代码是不是表现出竞争条件?的主要内容,如果未能解决你的问题,请参考以下文章

MPSC 队列:竞争条件

linux多线程--双buffer“无锁”设计

事务是不是会停止 MySQL 中的所有竞争条件问题?

嵌入式锁是不是会针对竞争条件增加任何价值?

如何在竞争条件下将主键值插入表中?

促进进程间竞争条件预防