为了账号安全,请及时绑定邮箱和手机立即绑定

何时以及为什么使用 go 的 atomic 包比较 =,+

何时以及为什么使用 go 的 atomic 包比较 =,+

Go
月关宝盒 2022-06-13 10:56:59
As go 的文档说明:由 AddT 函数实现的加法操作是原子等价的:*地址 += 增量返回*地址由 LoadT 和 StoreT 函数实现的加载和存储操作是“return *addr”和“*addr = val”的原子等价物。这是我的问题:为什么我应该使用“atomic.AddT”而不是“+”?为什么 'atomic.LoadT' 不是 '=' ?'=' 和 '+' 不是异常的吗?谁能给我一个显示它们之间差异的例子?
查看完整描述

3 回答

?
扬帆大鱼

TA贡献1799条经验 获得超9个赞

首先,你需要了解 go memory 模型:

https://golang.org/ref/mem

要理解的关键点是,goroutine 中变量写入的影响不一定对另一个 goroutine 可见,就像写入 goroutine 观察它们的方式一样。也就是说,如果一个 goroutine 将一个值写入一个变量a,然后再写入另一个变量b,另一个 goroutine 可能会以未指定的顺序看到这些写入。这就是为什么您需要像通道或互斥锁这样的并发原语。在通道操作或互斥操作之前发生的任何事情都将在此时对所有 goroutine 可见。

原子操作提供了类似的保证,尽管内存模型没有明确指定。

使用原子编写代码并不容易。您必须考虑所有可能的执行交错以确保没有竞争。坚持使用通道和互斥锁。正确的代码比快速但活泼的代码要好。


查看完整回答
反对 回复 2022-06-13
?
森林海

TA贡献2011条经验 获得超2个赞

想象一下,有 5 个 goroutine 同时访问初始化为 0 的同一个内存/源并试图增加它。常规增量“+”操作会导致数据竞争,因为由于同时操作无法保证状态被正确更新。最后,不能保证共享变量的值为 5

在这种情况下,原子操作会有所帮助,因为它们会锁定内存以供 goroutine 进行安全操作,因此不会观察到数据竞争

您还可以使用通道或互斥锁来锁定状态并安全操作,更推荐


查看完整回答
反对 回复 2022-06-13
?
慕容708150

TA贡献1831条经验 获得超4个赞

您根本 不应该使用包atomic

正如包装文档明确指出的那样

包 atomic 提供了用于实现同步算法的低级原子内存原语。

这些功能需要非常小心才能正确使用。除了特殊的低级应用程序外,最好使用通道或同步包的工具来完成同步。通过通信共享内存;不要通过共享内存进行通信。

它仅供专家使用。

你问:“'=' 和 '+' 不是异常的吗?” 不!Go 中没有任何东西(!)是原子的,除了包 atomic 中的原语(因此得名)、包同步提供的内容和通道操作。

所以不,您不能同时使用=+-,/等。而且你真的应该编写假设某些东西是原子的就是正确的代码。始终提供正确的同步(通过包同步)或通过渠道。


查看完整回答
反对 回复 2022-06-13
  • 3 回答
  • 0 关注
  • 138 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信