在不锁定的情况下同时读取函数指针是否安全? [英] Is it safe to read a function pointer concurrently without a lock?

查看:179
本文介绍了在不锁定的情况下同时读取函数指针是否安全?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有这个:

  go func(){
for range time.Tick(1 * time .Millisecond){
a,b = b,a
}
}()

其他地方:

  i:= a //<  - 这是否安全? 

对于这个问题, i 相对于原始 a b 。唯一的问题是阅读 a 是否安全。也就是说, a 有可能是 nil ,部分分配,无效,未定义,...其他任何其他比有效的价值?



我试过使它失败,但到目前为止,它总是成功(在我的Mac上)。



我一直无法找到超出此引号 Go Memory Model doc:


读取和写入大于单个机器字的值的行为为
以非特定顺序执行多个机器字大小的操作。


这是否意味着单个机器字写入是有效的原子?如果是这样,函数指针写入单个机器字操作?



更新:这里是 a 正确同步的解决方案

解决方案

通过未定义行为



未定义表示它说的是:

EM>未定义。这可能是你的程序会正常工作,也可能是错误的。它可能会导致由Go运行时提供的内存和类型安全性丢失(请参阅下面的示例)。它甚至可能会导致程序崩溃。或者它甚至可能导致地球爆炸(这个概率极小,甚至可能小于1e-40,但仍然......)。

这个 > undefined 意味着是, i 可能是 nil ,部分分配,无效,未定义,... a b 以外的任何内容。这个列表只是所有可能结果的一小部分。



不要以为某些数据竞赛是(或可能是)良性或无害的。由于你的代码写入变量 a in,所以它们可能是最糟糕的东西的来源。

一个goroutine并在另一个goroutine中读取它(它试图将它的值赋给另一个变量 i ),这是一个数据竞争,因此它是不安全的。在测试中它是否正确工作并不重要。人们可以把你的代码作为起点,扩展/构建它,并由于你最初的无害数据竞争而导致灾难。



相关问题,阅读 Golang为并发读取地图的安全性如何/写入操作? go lang中的同步不正确

强烈推荐阅读Dmitry Vyukov的博客文章:良性数据竞赛:什么可能出错?



另外一个非常有趣的博客文章展示了一个打破Go的记忆安全与故意数据竞争的例子: Golang数据竞赛打破记忆安全性


Suppose I have this:

go func() {
    for range time.Tick(1 * time.Millisecond) {
        a, b = b, a
    }
}()

And elsewhere:

i := a // <-- Is this safe?

For this question, it's unimportant what the value of i is with respect to the original a or b. The only question is whether reading a is safe. That is, is it possible for a to be nil, partially assigned, invalid, undefined, ... anything other than a valid value?

I've tried to make it fail but so far it always succeeds (on my Mac).

I haven't been able to find anything specific beyond this quote in the The Go Memory Model doc:

Reads and writes of values larger than a single machine word behave as multiple machine-word-sized operations in an unspecified order.

Is this implying that a single machine word write is effectively atomic? And, if so, are function pointer writes in Go a single machine word operation?

Update: Here's a properly synchronized solution

解决方案

Unsynchronized, concurrent access to any variable from multiple goroutines where at least one of them is a write is undefined behavior by The Go Memory Model.

Undefined means what it says: undefined. It may be that your program will work correctly, it may be it will work incorrectly. It may result in losing memory and type safety provided by the Go runtime (see example below). It may even crash your program. Or it may even cause the Earth to explode (probability of that is extremely small, maybe even less than 1e-40, but still...).

This undefined in your case means that yes, i may be nil, partially assigned, invalid, undefined, ... anything other than either a or b. This list is just a tiny subset of all the possible outcomes.

Stop thinking that some data races are (or may be) benign or unharmful. They can be the source of the worst things if left unattended.

Since your code writes to the variable a in one goroutine and reads it in another goroutine (which tries to assign its value to another variable i), it's a data race and as such it's not safe. It doesn't matter if in your tests it works "correctly". One could take your code as a starting point, extend / build on it and result in a catastrophe due to your initially "unharmful" data race.

As related questions, read How safe are Golang maps for concurrent Read/Write operations? and Incorrect synchronization in go lang.

Strongly recommended to read the blog post by Dmitry Vyukov: Benign data races: what could possibly go wrong?

Also a very interesting blog post which shows an example which breaks Go's memory safety with intentional data race: Golang data races to break memory safety

这篇关于在不锁定的情况下同时读取函数指针是否安全?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆