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

golang中不正确的同步

golang中不正确的同步

Go
蝴蝶刀刀 2021-11-15 20:45:14
当我查看 golang 内存模型文档(链接)时,我在 go lang 上发现了一个奇怪的行为。该文档说下面的代码可能会发生 g 打印 2 然后打印 0。var a, b intfunc f() {    a = 1    b = 2}func g() {    print(b)    print(a)}func main() {    go f()    g()}这只是常规问题吗?因为我很好奇为什么变量 'b' 的值分配可以在 'a' 之前发生?即使 'a' 和 'b 的赋值发生在不同的线程中(不在主线程中),是否必须确保在它自己的线程中在 'b' 之前分配 'a'?(因为 ' a' 先出现,然后 'b' 出现)有人能清楚地告诉我这个问题吗?
查看完整描述

1 回答

?
梦里花落0921

TA贡献1772条经验 获得超6个赞

在任何函数开始执行之前,变量ab使用它们各自类型的零值(0在 的情况下int)进行分配和初始化,在这一行:

var a, b int

可能会改变的是在f()函数中为它们分配新值的顺序。

引用该页面:之前发生

在单个 goroutine 中,读取和写入必须按照程序指定的顺序执行。也就是说,只有当重新排序不会改变语言规范定义的 goroutine 中的行为时,编译器和处理器才可以重新排序在单个 goroutine 中执行的读取和写入。由于这种重新排序,一个 goroutine 观察到的执行顺序可能与另一个 goroutine 感知的顺序不同。例如,如果一个 goroutine 执行a = 1; b = 2;,另一个可能会在 的更新值b之前观察 的更新值a

如果重新排序它们不会在同一个 goroutine 中产生影响ab则分配给和可能不会按照您编写它们的顺序发生。例如,如果首先更改 的值b更有效(例如,因为其地址已加载到寄存器中),则编译器可能会对它们重新排序。如果更改赋值顺序会(或可能)在同一个 goroutine 中导致问题,那么显然编译器不允许更改顺序。由于f()函数的 goroutine 对变量不做任何处理,a并且b在赋值之后,编译器可以自由地以任何顺序执行赋值。

由于上述示例中的 2 个 goroutine 之间没有同步,因此编译器不会检查重新排序是否会导致其他 goroutine 出现任何问题。它没有必要。

Buf 如果你同步你的 goroutines,编译器会确保在“同步点”没有不一致:你将保证在那个点两个分配都将“完成”;因此,如果“同步点”在print()调用之前,那么您将看到分配的新值打印:21


查看完整回答
反对 回复 2021-11-15
  • 1 回答
  • 0 关注
  • 178 浏览
慕课专栏
更多

添加回答

举报

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