interview-go icon indicating copy to clipboard operation
interview-go copied to clipboard

常见语法题目 一 的第6题,CAS操作

Open vdanic opened this issue 4 years ago • 3 comments

题目: 6、请说明下面代码书写是否正确。

var value int32

func SetValue(delta int32) {
	for {
		v := value
		if atomic.CompareAndSwapInt32(&value, v, (v+delta)) {
			break
		}
	}
}

解析:

atomic.CompareAndSwapInt32 函数不需要循环调用。

疑问: atomic.CompareAndSwapInt32仅提供了原子交换的操作,我理解SetValue这个函数的用意应该就是让value加上delta大小的数值,所以在atomic.CompareAndSwapInt32操作失败,返回False的时候应该要循环重新读取新值然后进行CAS操作,直到atomic.CompareAndSwapInt32返回为True。 解析中的不需要循环调用,是否描述不正确。

vdanic avatar Nov 09 '21 09:11 vdanic

我也认为需要循环调用,如果是订单数量累计的话,其他groutinue也在进行原子性操作的话,其实v期望的数是不对的,那么就需要循环重新去全局变量里面value的值,重新compare and swap.

zhepoch avatar Dec 20 '21 08:12 zhepoch

答案意思是不是要说应该用atomic.AddInt32()

terryli1643 avatar Jul 17 '23 09:07 terryli1643

这段代码在语法上是正确的,并且其逻辑也是可以正确执行的。它利用了 Go 语言的 atomic 包中提供的 CompareAndSwapInt32 函数,来达到原子性地更新 value 变量的效果。

SetValue 函数定义了以下过程:

  1. 在一个无限循环内读取全局变量 value 到局部变量 v

  2. 使用 CompareAndSwapInt32 函数尝试原子性地将 valuev 更新为 v + delta

    • 如果 value 仍等于 v(没有其他协程已经修改了 value),则更新 value 并退出循环。
    • 如果 value 已经不等于 v(其他协程已经修改了 value),则循环重试整个过程。

SetValue 函数的目的是确保在多个协程可能同时尝试更新 value 的情况下,始终能够正确地增加 deltavalue 上。atomic.CompareAndSwapInt32 的原子操作保证了同一时间只有一个操作可以成功地改变 value

这样的代码通常用于无锁编程模式,在高并发的情境中需要确保变量的更改操作不会互相干扰时,这种方式是非常有用的。

然而,需要注意的是,虽然这种方法提供了一种无锁更新共享变量的方式,但它也可能会导致高竞争的情况下出现活锁问题。这是因为在高度竞争的环境下,SetValue 函数可能会不断失败并重试。因此,这种方式最适用于更新冲突不是很频繁发生的场景中。

seakee avatar Apr 02 '24 11:04 seakee