nic*_*bot 6 concurrency go goroutine
假设我有这个:
go func() {
for range time.Tick(1 * time.Millisecond) {
a, b = b, a
}
}()
Run Code Online (Sandbox Code Playgroud)
其他地方:
i := a // <-- Is this safe?
Run Code Online (Sandbox Code Playgroud)
对于这个问题,i与原始a或者相关的价值是不重要的b.唯一的问题是阅读a是否安全.也就是说,是否有可能a被nil部分分配,无效,未定义,......除了有效值之外的任何东西?
我试图让它失败,但到目前为止它总是成功(在我的Mac上).
在Go Go Memory Model文档中,我无法找到超出此引用的任何特定内容:
大于单个机器字的值的读取和写入表现为以未指定的顺序进行的多个机器字大小的操作.
这是否意味着单个机器字写入实际上是原子的?并且,如果是这样,函数指针写入Go单个机器字操作?
更新:这是一个正确同步的解决方案
icz*_*cza 15
从多个够程,其中它们中的至少一个是写入任何变量不同步,并发访问是未定义的行为通过将GO记忆模型.
未定义意味着它所说的:未定义.可能是您的程序正常工作,可能会无法正常工作.它可能导致Go运行时提供的内存和类型安全性丢失(参见下面的示例).它甚至可能会使您的程序崩溃.或者它甚至可能导致地球爆炸(概率极小,甚至可能低于1e-40,但仍然......).
这种不确定你的情况意味着,是的,i可以nil,部分转让的,无效的,不确定的,......比任何其他东西a或b.该列表只是所有可能结果的一小部分.
不要以为某些数据竞赛是(或可能是)良性或无害的.如果无人看管,它们可能是最糟糕的事情的根源.
由于您的代码a在一个goroutine中写入变量并在另一个goroutine中读取它(它试图将其值分配给另一个变量i),因此它是一个数据竞争,因此它不安全.如果在您的测试中它"正确"工作并不重要.人们可以将您的代码作为起点,扩展/构建它,并由于您最初的"无害"数据竞争而导致灾难.
作为相关问题,请阅读Golang如何安全地进行并发读/写操作?go lang中的同步和不正确.
强烈建议阅读Dmitry Vyukov的博客文章:良性数据竞赛:可能出现什么问题?
这也是一篇非常有趣的博客文章,其中展示了一个以故意数据竞争打破Go的内存安全性的例子:Golang数据竞争打破内存安全
就Race condition 而言,这是不安全的。简而言之,我对竞争条件的理解是,当有多个异步例程(协程、线程、进程、goroutines 等)试图访问相同的资源并且至少一个是写入操作时,因此在您的示例中,我们有 2 goroutines 读取和写入函数类型的变量,我认为从并发的角度来看,重要的是这些变量在某处有一个内存空间,我们试图在该部分内存中读取或写入。
简短回答:只需使用带有
或的-race标志运行您的示例,您就会看到检测到的数据竞争。go run -racego build -race