当前位置: 首页 > 面试题库 >

Go lang中的同步不正确

酆奇文
2023-03-14
问题内容

在查看golang内存模型文档(link)时,我发现go
lang上有一个奇怪的行为。该文档说,下面的代码可能会发生,g依次打印2和0。

var a, b int

func f() {
    a = 1
    b = 2
}

func g() {
    print(b)
    print(a)
}

func main() {
    go f()
    g()
}

这是例行公事吗?因为我很好奇为什么变量’b’的值赋值可以先于’a’赋值?即使’a’和’b的值分配将在不同的线程中发生(不在主线程中),是否也必须确保在其自己的线程中将’a’分配在’b’之前?(因为分配’
a’首先出现,’b’之后出现)有人可以清楚地告诉我这个问题吗?


问题答案:

在开始执行任何函数之前,在以下行中使用各自的类型(在中为)的零值来分配和初始化变量,a并在此行:b``0``int

var a, b int

可能更改的是在f()函数中将新值分配给它们的顺序。

从该页面引用:之前发生:

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

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

由于在上面的示例中这两个goroutine之间没有同步,因此编译器不费力气检查重新排序是否会在另一个goroutine中引起任何问题。不必。

另外,如果您对goroutine进行同步,则编译器将确保在“同步点”不会出现任何不一致之处:您将确保在这时两个分配都将“完成”;因此,如果“同步点”在print()调用之前,那么您将看到打印的已分配新值:21



 类似资料:
  • 您可以通过 Bluetooth 连接,以无线方式,将数据从手表传输至 Polar Flow 应用程式。或者您可以使用 USB 端口和 FlowSync 软件,将手表与 Polar Flow 网络服务同步。若要在手表与 Flow 应用程式之间同步数据,您需要拥有 Polar 账户。如果您想将手表上的数据直接同步到网络服务,除了 Polar 账户,您还需要 FlowSync 软件。如果您已设置手表,已

  • 您可以通过 Bluetooth 连接,以无线方式,将数据从手表传输至 Polar Flow 应用程式。或者您可以使用 USB 端口和 FlowSync 软件,将手表与 Polar Flow 网络服务同步。若要在手表与 Flow 应用程式之间同步数据,您需要拥有 Polar 账户。如果您想将手表上的数据直接同步到网络服务,除了 Polar 账户,您还需要 FlowSync 软件。如果您已设置手表,已

  • 您可以使用 FlowSync 软件通过 USB 端口传输来自 A370 的数据,或使用 Flow 应用程式通过 Bluetooth Smart® 进行无线传输。若要在 A370 和 Flow 网络服务与应用程式之间同步数据,您需要拥有 Polar 账户和 FlowSync 软件。如果您在 flow.polar.com/start中设置了 A370,说明您已创建了该账户并下载了该软件。当您开始使用

  • 我试图设置两个线程,它们在另一个类中增加或减少一个整数。我对这个属性的同步有一些问题。 这是我的主要类,我在其中设置了线程和计数器类: 这是我的柜台课: 这是我的Thread1类:(runnable类是一样的,只是用“实现Runnable”而不是“扩展线程”) 但是,我的输出始终是10000000。尽管我同步了两种方法。有人能解释这是怎么回事吗?

  • 问题内容: 我不确定这是否是同步我的的正确方法。 我有一个 从函数传递过来的。 现在,我正在尝试使其同步。这是否正确同步了我的对象? 问题答案: 您要进行两次同步,这是没有意义的,可能会减慢代码的速度:在列表上进行迭代时所做的更改需要整个操作的同步,在这种情况下,使用Using 这样做是多余的(它创建了一个包装程序来同步各个操作)。 但是,由于您要完全清空列表,因此迭代删除第一个元素是最糟糕的方法

  • 问题内容: 因此,我正在考虑建立一个业余项目,这只是为了完成我的编程/设计。 它基本上是一个多线程的网络蜘蛛,更新了相同的数据结构object-> int。 因此,为此使用数据库绝对是矫kill过正,而我唯一想到的就是用于包含我的数据结构的线程安全单例。http://web.archive.org/web/20121106190537/http://www.ibm.com/developerwor