内容简介:"Do not communicate by sharing memory; instead, share memory by communicating" 这句话在讲 Golang 并发的好多文章里看到过,仿佛是一个格言一般。然而对于它的真正含义一直不是很清楚。最近看到了如下的代码,才对这句话有所思考和理解。摘自
"Do not communicate by sharing memory; instead, share memory by communicating" 这句话在讲 Golang 并发的好多文章里看到过,仿佛是一个格言一般。然而对于它的真正含义一直不是很清楚。
最近看到了如下的代码,才对这句话有所思考和理解。
摘自 https://golang.org/ref/mem 的一段 错误 的并发代码:
var a string var done bool func setup() { a = "hello, world" done = true } func main() { go setup() for !done { } print(a) }
这段代码是典型的 communicate by sharing memory 。而官网说到这段 错误的 代码可能的结局有两种不能接受:
-
print(a)
打印出来的是空字符串。 -
main
函数陷入死循环。
先来解释一下1:Go的内存模型里说到 “happen before” 这样一条原则,也讲了很多种遵循这条原则的操作,比如在一个 goroutine 中如果对一个变量的写w和读r,如果w在代码上位于r的前面,则 w 先于 r 发生。而这里对 a 的写操作 和 对 done 的写操作并不属于 happen before 的范围。也就是说,它们有可能 同时发生 甚至 顺序颠倒 。所以在 检测到 done 为 true 时,a 还未赋值的情况是有可能发生的。
再来看2:如果在main
函数的一开始或者在init
函数中通过runtime.GOMAXPROCS(1)
将并发数设置为1,那么setup
永远不会执行,main
将会陷入死循环。
官网也讲到了 Go 的各种并发元语是如何满足 happens-before 原则的。思考一下,上述例子在 GOMAXPROCS = 1 时是无法正常执行的,那么那些正确的并发程序在 GOMAXPROCS = 1 时表现如何呢?所谓 正确 的并发程序,goroutine之间应当是通过并发元语来沟通协作的,那么他们之间必然有某种 happen-before 的约束存在,happen-before 的实质作用其实是将两个goroutine的某一部分串行起来,使用并发原语,也就是为了将需要串行的部分串行起来,这样即使是 GOMAXPROCS = 1,多个goroutine 也是能够正确协作的。
所以对于 “Do not communicate by sharing memory; instead, share memory by communicating” 这句话,我认为 share memory by communicating 的 communicating 不光是指 channel,Go 的并发元语都是 communicating,Mutex,Once,atomic, channel 等都是 goroutine 之间沟通的正确方式。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Java并发系列—并发编程基础
- [Java并发-17-并发设计模式] Immutability模式:如何利用不变性解决并发问题?
- JAVA并发编程之并发模拟工具
- Java并发系列—并发编程的挑战
- Core Java 并发:理解并发概念
- [Java并发-11] 并发容器的使用
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。