一尘不染

说明:不要通过共享内存进行通信;通过通信共享内存

go

我想知道这个著名报价的最真实的解释是什么:

不要通过共享内存进行交流;通过通信共享内存。(R.派克)

Go Memory Model中,我可以阅读以下内容:

通道上的发送发生在该通道上的相应接收完成之前。(Golang规格)

还有一篇专门的golang文章解释了报价。而关键的贡献是一个工作例子也由Andrew
G.

好。有时谈论太多....我是从“内存规范”引用中得出的,也可以通过查看工作示例来得出:

goroutine1通过通道发送(任何东西)到goroutine2之后,goroutine1通过同一通道接收到之后,goroutine1完成的所有更改(在内存中的任何地方)必须对goroutine2可见。(我的Golang引理:)

因此,我得出了著名报价的脚踏实地解释:

要在两个goroutine之间同步内存访问,您无需通过通道发送该内存。足以从通道接收(甚至什么也没有)。您将在goroutine发送(到通道)时看到(在任何地方)写入的所有更改。(当然,假设没有其他goroutine正在写入同一内​​存。)
更新(2)8-26-2017

我实际上有两个问题:

1)我的结论正确吗?

2)我的解释有帮助吗?

更新(1) 我假设没有 缓冲的通道 。让我们首先限制自己,以免因过多的未知而大修自己。

拜托,让我们也关注两个通过单个通道进行通信的goroutine的简单用例以及相关的内存效果,而不是最佳实践-超出了本问题的范围。

为了更好地理解我的问题的范围,假设goroutine可以访问任何类型的内存结构(不仅是primitve的),而且可以是一个大的内存结构,可以是字符串,映射,数组等。


阅读 226

收藏
2020-07-02

共1个答案

一尘不染

从本质上讲,是的。由于通道操作施加了排序约束,因此在通道发送之前分配给变量的任何值都可以在通道读取之后进行观察。但重要的是要记住方程式的另一部分:如果您想
保证
要确保观察到这些值,则必须确保在写入和读取之间没有其他人可以写入这些变量。显然可以使用锁,但同时毫无意义,因为如果您已经将锁和跨线程内存修改结合在一起,那么从通道中可以获得什么好处?您可以传递诸如布尔值之类的简单信息,作为允许对全局数据进行独占访问的令牌,并且就内存模型保证而言(只要您的代码没有错误),
是100%正确的 这可能只是一个糟糕的设计,
因为您将在没有充分理由的情况下将所有内容隐式化并按距离进行操作;显式传递数据通常会更加清晰,并且不容易出错。

2020-07-02