在学习golang的过程中,当尝试理解内存模型规范中描述的通道通信时,我有些困惑,其中描述如下:
对于非缓冲通道,发送操作(B)将被阻塞,直到接收者准备好接收值(A)为止?(比如:B开始执行并一直等待,直到A执行)这个描述准确吗?
我在Effective Go spec中发现了以下陈述,但与我的理解仍有差异...所以请问有人能用简单明了的方式来解释一下吗?
“接收者总是阻塞,直到有数据可接收。如果通道未缓存,则发送方将阻塞,直到接收方接收到该值。如果通道具有缓存,则发送方仅阻塞,直到该值已复制到缓存中;如果缓存已满,则这意味着等待某个接收方检索一个值。”
第1、2条规则很清晰易懂,而对于第3条规则,我真的感到困惑,因为它似乎与其他规则相反…… 我是否漏掉了什么关于非缓冲通道的特殊说明?或者如果按照规范中的示例将其理解为以下内容,我是正确的吗?
- 从通道发送数据在相应的接收操作完成之前发生。
- 关闭通道在因通道关闭而返回零值的接收操作之前发生。
- 从非缓冲通道接收数据在发送操作完成之前发生。
- 在容量为C的通道上第k个接收操作在第k+C个发送操作完成之前发生。
var c = make(chan int)
var a string
func f() {
a = "hello, world"
<-c // A
}
func main() {
go f()
c <- 0 // B
print(a)
}
对于非缓冲通道,发送操作(B)将被阻塞,直到接收者准备好接收值(A)为止?(比如:B开始执行并一直等待,直到A执行)这个描述准确吗?
我在Effective Go spec中发现了以下陈述,但与我的理解仍有差异...所以请问有人能用简单明了的方式来解释一下吗?
“接收者总是阻塞,直到有数据可接收。如果通道未缓存,则发送方将阻塞,直到接收方接收到该值。如果通道具有缓存,则发送方仅阻塞,直到该值已复制到缓存中;如果缓存已满,则这意味着等待某个接收方检索一个值。”
x
和y
,同时满足这两个关系:x HB y
和y HB x
。规则1和3共同大致表示:“在无缓冲通道上发送和接收会适当地同步并像您期望的那样工作(无论 CPU 如何重新组织您的指令,内存缓存如何缓存等等)。” - Volkerx HB y
和y HB x
都是正确的,哈哈。可能我需要将事件e
分成不同的原子阶段,例如开始、处理和结束,以便更好地理解这个“happens-before”术语…谢谢! - Roy Ling