如果我像这样定义一种新的“状态”:
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”具有相同的并发效果吗?
答案 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
时相同的并发保证。