我想知道对这句名言最实事求是的解释是什么:

不要通过共享记忆来交流,要通过交流来分享记忆.(R.派克)

The Go Memory Model分钟里,我可以读到这个:

通道上的发送发生在来自该通道的相应接收完成之前.(Golang Spec)

还有一个专门的golang article解释这句话.关键贡献也是由安德鲁·G.

井.有时候说得太多了……我从Memory Spec报价中推导出以下内容,并通过查看工作示例得出以下结论:

goroutine1通过通道向goroutine2发送(任何内容)后,goroutine1所做的所有更改(内存中的任何位置)必须在goroutine2通过同一通道接收后可见.(我的Golang引理:)

因此,我得出了对这句名言的实事求是的解释:

要在两个Goroutine之间进行同步内存访问,您不需要通过通道发送该内存.足够好的是从通道接收(甚至什么都没有).在发送时,您将看到Goroutine发送(到通道)时(在任何位置)写入的任何更改.(当然,假设没有其他Goroutine正在写入相同的内存.)Update (2) 8-26-2017

我实际上有两个问题:

1) Is my conclusion correct?

2) Does my explanation help?

Update (1)个 我想是unbuffered channels吧.让我们先把自己限制在这一点上,以避免用太多的未知因素来彻底 retrofit 我们自己.

请让我们也关注一个简单的用例,两个Goroutine通过一个通道进行通信,以及相关的记忆效应,而不是最佳实践——这超出了本问题的范围.

为了更好地理解我的问题的范围,假设goroutine可以访问任何类型的内存 struct -不仅仅是primitve内存 struct -它可以是很大的内存 struct ,可以是字符串、映射、数组等等.

推荐答案

本质上,是的.在通道发送之前分配给变量的任何值都有资格在通道读取之后观察,因为通道操作施加了排序约束.但记住等式的另一部分很重要:如果你想知道这些值是否被观察到,你必须确保在写和读之间没有其他人可以写入这些变量.显然,使用锁是可能的,但同时也是毫无意义的,因为如果您已经将锁和跨线程内存修改结合起来,那么您从通道中获得了什么好处?你可以传递一些简单的东西,比如布尔值,作为一个允许独占访问全局数据的令牌,它在内存模型保证方面是guarantee%正确的(只要你的代码没有bug),it would just probably be a bad design因为你会在没有充分理由的情况下,使事情都隐式化,并在距离上采取行动;显式传递数据通常会更清晰,更不容易出错.

Go相关问答推荐

为什么我不能使用Docker从本地访问我的Gin应用程序?

错误.如果它包含切片,则返回FALSE

重新赋值变量时未清除动态类型-这是错误吗?

如何使用 AWS sdk 在 Go 中正确解组 PartiQL 查询的结果?

Go 中的sync.Cond 与 Wait 方法

启动套接字服务器会干扰 gRPC/http 客户端服务器通信 Golang

Go Template 动态获取变量

我应该先解锁然后再广播吗?

使用Go和Operator SDK通过API调用设置Kubernetes Pods的安装步骤

使用 httptest 对 http 请求进行单元测试重试

Golang crypto/rand 线程安全吗?

Gremlin-Go:树步骤不可序列化

为什么 `append(x[:0:0], x...)` 将切片复制到 Go 中的新后备数组中?

当函数返回一个函数时,为什么 Go 泛型会失败?

具有两个或多个模型的 GORM 查询

GRPC 元数据未在 Go 中更新

在删除级联时无法在 Gorm 中按预期工作

GoLang 遍历 yaml 文件

在 connect-go 拦截器中修改响应体

是否可以使用按位运算在随机 unicode 字符串中找到重复字符?