关于匿名函数使用共享变量的问题

weixin_38058748 2019-09-20 10:52:24
环境:go1.7.3 win7 64bit

代码1的执行结果是隔一秒只打印0,不符合预期
```
0
0
0
...
```
把代码1改成代码2,结果就对了
```
353036023
713389754
1073135313
...
```
这是个什么情况,有大佬知道吗

**代码1:**
```
package main

import (
"fmt"
"time"
)

func main() {
i := 0
go func () {
for true {
//隔一秒打印i
time.Sleep(1000000000)
fmt.Println(i)
}
}()

for true {
i++
}
}
```

**代码2:**
```
package main

import (
"fmt"
"time"
)

func main() {
i := 0
go func () {
for true {
i++
}
}()

for true {
//隔一秒打印i
time.Sleep(1000000000)
fmt.Println(i)
}
}
```
...全文
62 13 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
weixin_38097244 2019-09-20
  • 打赏
  • 举报
回复
对的,后面我在两个循环里面都打印i,结果就不是0了
weixin_38114194 2019-09-20
  • 打赏
  • 举报
回复
如果你在循环都加了打印,是有区别的,编译器会插入调度代码。
weixin_38125461 2019-09-20
  • 打赏
  • 举报
回复
这个网页我打不开, 我是初学,各种想法都想试下,以后会避开这个坑
weixin_38126381 2019-09-20
  • 打赏
  • 举报
回复
我觉得不是data race的问题,应该是编译器优化的问题
weixin_38127863 2019-09-20
  • 打赏
  • 举报
回复
初学go,不太懂go的编译优化策略,谢谢你的方法
weixin_38132882 2019-09-20
  • 打赏
  • 举报
回复
复制粘贴链接
weixin_38062043 2019-09-20
  • 打赏
  • 举报
回复
这个问题在我电脑上,两种情况打印出的结果都是 0。 环境:go version go1.12 linux/amd64
weixin_38063369 2019-09-20
  • 打赏
  • 举报
回复
真奇怪,我记得上午我测试的时结果是不一样的。然后刚才我又测试了一下,怎么结果都是0了?题主确定结果不一样?
weixin_38066448 2019-09-20
  • 打赏
  • 举报
回复
编译器直接没生成 i++ 的汇编代码,不知道为何编译器直接没编译出 i++ 这个命令,可能编译器做了判断这种简单的for是没意义的。改复杂一点,编译器识别不出来,就可以了。如下图
weixin_38072110 2019-09-20
  • 打赏
  • 举报
回复
上面的截图不好看代码,我发这里,你可以自己研究一下 ```go func testg1() { i := int64(0) go func() { for true { //隔一秒打印i time.Sleep(1000000000) fmt.Println(i) // 0 // runtime.GC() // forever block } }() for true { i++ } } func testg2() { i := int64(0) go func() { for true { //隔一秒打印i time.Sleep(1000000000) fmt.Println(atomic.LoadInt64(&i)) // 778880009 } }() for true { atomic.AddInt64(&i, 1) } } func testg4() { i := int64(0) go func() { for true { i++ } }() for true { //隔一秒打印i time.Sleep(1000000000) fmt.Println(i) // 0 // runtime.GC() // forever block } } func testg5() { i := int64(0) go func() { for true { //隔一秒打印i time.Sleep(1000000000) fmt.Println(i) // xxxx // runtime.GC() // forever block } }() for true { f := func() { i++ y := int64(0) y++ _ = y * i } f() } } ``` 生成汇编代码,用 go tool compile -S go文件
weixin_38077132 2019-09-20
  • 打赏
  • 举报
回复
Golang大佬Ross Cox说了:“Don’t communicate by sharing memory. (Especially without any synchronization.)。” 具体原因请看“https://golang.org/ref/mem”。楼上汇编分析有道理。
weixin_38088241 2019-09-20
  • 打赏
  • 举报
回复
当data race存在时,程序运行的行为是不确定的,所以这样的代码没有实际意义
weixin_38091562 2019-09-20
  • 打赏
  • 举报
回复
我后面用ubuntu go 1.10试了下,也都是0

473

社区成员

发帖
与我相关
我的任务
社区描述
其他技术讨论专区
其他 技术论坛(原bbs)
社区管理员
  • 其他技术讨论专区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧