刚刚接触go语言,对于其内存模型不是很理解。能够明白通道通信,锁等内容。。但是对于最后的几个错误同步的例子不明白为什么?
例如:
var a string
var done bool
func setup() {
a = "hello, world"
done = true
}
func main() {
go setup()
for !done {
}
print(a)
}
和前面一样,这里不保证在 main 中对 done 的写入的监测, 蕴含对 a 的写入也进行监测,因此该程序也可能会打印出一个空字符串。 更糟的是,由于在两个线程之间没有同步事件,因此无法保证对 done 的写入总能被 main 监测到。main 中的循环不保证一定能结束。
上面这段说明中说有可能会出问题,打印空字符之类的,但是我没想白,不是只有等done为true之后才会进行print嘛,那时候不是已经进行赋值了嘛? 另外用go1.11 尝试运行多次,结果也是可以输出hello world的
这个问题明明文档一开始就写了啊?go的内存模型就是这样的啊,文档例子里就有作者提的代码。[The Go Memory Model](https://golang.org/ref/mem) 中说了 `Within a single goroutine, reads and writes must behave as if they executed in the order specified by the program. That is, compilers and processors may reorder the reads and writes executed within a single goroutine only when the reordering does not change the behavior within that goroutine as defined by the language specification. Because of this reordering, the execution order observed by one goroutine may differ from the order perceived by another. For example, if one goroutine executes a = 1; b = 2;, another might observe the updated value of b before the updated value of a.`
大概意思就是
`不改变语言规范定义的行为时,编译器和处理器才可以重新排序在单个goroutine中执行的读取和写入。由于这种重新排序,一个goroutine观察到的执行顺序可能与另一个goroutine所感知的顺序不同。例如,如果一个goroutine执行a = 1; b = 2;,另一个可能会在a的更新值之前观察到b的更新值。`
也就是说对于题主的例子:
```
a = "hello, world"
done = true
```
在main goroutine看来a和done的顺序是不确定的,如果编译器和cpu进行了重排,就有可能done比a先执行的。
#23
更多评论
好像不关内存什么事吧,是你基础没有学好
首先 done 的初始化应该为 false 就是 0,一般情况下 所有的语言 bool 类型 初始化都为 false
然后 for 循环,!done ,差不多相当于 只要是 done 为false 就会一直循环下去,直到 done 变为 true。
也就是 不关 你的 setup 什么时候执行,一旦执行后,done 变为 true,for 循环结束跳出,之后 print
#1