golang中定义类型的原子操作

时间:2018-06-15 07:58:55

标签: go

如果我像这样定义一种新的“状态”:

type State int32

类型'State'的值是否可以应用原子操作,例如'atomic.StoreInt32()'?

如果没有,为什么?

如果可以,是否可以按以下方式应用?

func SetAndGet(s State, n State) State {
    si := int32(s)
    ni := int32(n)
    return State(atomic.SwapInt32(&si, ni))
}

更新

根据@ icza的回答,代码修改如下。

func SetAndGetState(s *State, n State) State {
    return State(atomic.SwapInt32((*int32)(s), int32(n)))
}
func SetAndGetInt(s *int32, n int32) State {
    return State(atomic.SwapInt32((*int32)(s), int32(n)))
}
var s1 State = 1
var i1 int32 = 1
SetAndGetState(&s1, 2)
SetAndGetInt(&i1, 2)

我已经尝试了我的代码和@ icza的代码。他们都成功了。 'State'的结果似乎与int32相同。我想知道的是: 在高并发情况下,原子操作对定义类型“State”和“int32”具有相同的并发效果吗?

1 个答案:

答案 0 :(得分:1)

通常对变量执行原子操作。

调用函数时,将复制传递的值。没有理由对仅由函数使用的局部变量(函数参数)执行原子操作。

您可能想要执行原子操作,例如在一个全局变量上。并且SetAndGet()能够做到这一点,你必须传递它的地址(传递它的值只是复制它)。

并且您无法创建传递的指针的本地副本(既不是指向的值),您必须将您直接获得的地址传递给atomic.SwapInt32()。要做到这一点,只需将*State指针转换为*int32即可。这是可能的,因为State的基础类型为int32

func SetAndGet(s *State, n State) State {
    return State(atomic.SwapInt32((*int32)(s), int32(n)))
}

测试它:

var s State

func main() {
    fmt.Println(SetAndGet(&s, 1))
    fmt.Println(SetAndGet(&s, 2))
    fmt.Println(SetAndGet(&s, 3))
}

输出(在Go Playground上尝试):

0
1
2

使用上述解决方案,您将获得与使用int32而不是State时相同的并发保证。