求回答:下面代码的结果

lhtzbj12 · 2018-01-05 13:19:15 · 1377 次点击 · 大约8小时之前 开始浏览    置顶
这是一个创建于 2018-01-05 13:19:15 的主题,其中的信息可能已经有所发展或是发生改变。

package main

import (
    "fmt"
    "runtime"
    "sync"
)

func init() {
    fmt.Println("Current Go Version:", runtime.Version())
}
func main() {
    runtime.GOMAXPROCS(1)
    count := 10
    wg := sync.WaitGroup{}
    wg.Add(count * 2)
    for i := 0; i < count; i++ {
        go func() {
            fmt.Printf("[%d]", i)
            wg.Done()
        }()
    }
    for i := 0; i < count; i++ {
        go func(i int) {
            fmt.Printf("-%d-", i)
            wg.Done()
        }(i)
    }
    wg.Wait()
}

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1377 次点击  
加入收藏 微博
14 回复  |  直到 2018-01-10 12:08:31
lhtzbj12
lhtzbj12 · #1 · 7年之前
channel
channel · #2 · 7年之前

这是很经典的问题

momaek
momaek · #3 · 7年之前

闭包 for 取 i

lhtzbj12
lhtzbj12 · #4 · 7年之前
channelchannel #2 回复

这是很经典的问题

是的,很精典,但是今天发现答案是 -9-[10][10][10][10][10][10][10][10][10][10]-0--1--2--3--4--5--6--7--8- 不知道为会第二个循环会先执行一次后,再执行第一个循环,而且每次答案都 一样

lhtzbj12
lhtzbj12 · #5 · 7年之前
momaekmomaek #3 回复

闭包 for 取 i

-9-[10][10][10][10][10][10][10][10][10][10]-0--1--2--3--4--5--6--7--8- 不知道为会第二个循环会先执行一次后,再执行第一个循环,而且每次答案都 一样

channel
channel · #6 · 7年之前

请勿依赖调度。具体调度算法,每个版本可能都不一样。

leavesdrift
leavesdrift · #7 · 7年之前

谁能讲一下这是什么情况么?不太懂。

marlonche
marlonche · #8 · 7年之前
leavesdriftleavesdrift #7 回复

谁能讲一下这是什么情况么?不太懂。

没必要深究这些,依照规范里面明确说明的方式来同步准没错

momaek
momaek · #9 · 7年之前
lhtzbj12lhtzbj12 #5 回复

#3楼 @momaek -9-[10][10][10][10][10][10][10][10][10][10]-0--1--2--3--4--5--6--7--8- 不知道为会第二个循环会先执行一次后,再执行第一个循环,而且每次答案都 一样

这个你要去看 golang 的调度算法了,具体是什么也不是一句话就可以说清楚的

lhtzbj12
lhtzbj12 · #10 · 7年之前
momaekmomaek #9 回复

#5楼 @lhtzbj12 这个你要去看 golang 的调度算法了,具体是什么也不是一句话就可以说清楚的

好的,谢谢

lhtzbj12
lhtzbj12 · #11 · 7年之前
marlonchemarlonche #8 回复

#7楼 @leavesdrift 没必要深究这些,依照规范里面明确说明的方式来同步准没错

好的,谢谢

qclaogui
qclaogui · #12 · 7年之前

猜想代码想要说明两个问题:

一是匿名函数中的循环变量快照问题:第一个for循环问题(一般情况下这么认为这段代码是有问题的)的原因在于循环变量的作用域,for循环语句引入了新的词法块,循环变量i在这个词法块中被声明。在该循环中生成的所有函数值都共享相同的循环变量。需要注意,函数值中记录的是循环变量的内存地址,而不是循环变量某一时刻的值,后续的迭代会不断更新i的值,当函数执行时,for循环已完成,i中存储的值等于最后一次迭代的值。为了解决这个问题,我们会引入一个局部变量,作为循环变量的副本,如图: image.png

二是, GOMAXPROCS设置为1,是设置一个cpu核心去处理,将影响goroutine的并发,代码中的go func()相当于串行执行(不是并行),所有输出结果始终是一样

leavesdrift
leavesdrift · #13 · 7年之前
qclaoguiqclaogui #12 回复

猜想代码想要说明两个问题: **一是匿名函数中的循环变量快照问题**:第一个for循环问题(一般情况下这么认为这段代码是有问题的)的原因在于循环变量的作用域,for循环语句引入了新的词法块,循环变量`i`在这个词法块中被声明。在该循环中生成的所有函数值都共享相同的循环变量。**需要注意**,函数值中记录的是循环变量的内存地址,而不是循环变量某一时刻的值,后续的迭代会不断更新`i`的值,当函数执行时,for循环已完成,`i`中存储的值等于最后一次迭代的值。为了解决这个问题,我们会引入一个局部变量,作为循环变量的副本,如图: ![image.png](https://static.studygolang.com/180109/9d998e0fd80d154cc8e8d4603c37d57c.png) **二是**, GOMAXPROCS设置为1,是设置一个cpu核心去处理,将影响goroutine的并发,代码中的go func()相当于串行执行(不是并行),所有输出结果始终是一样

关键在于第一个9。

qclaogui
qclaogui · #14 · 7年之前
leavesdriftleavesdrift #13 回复

#12楼 @qclaogui 关键在于第一个9。

Go 有一套自己的管理、调度、执行goroutine的方式就是我们说的Go的并发, 所以我们可以假装这样理解(代码中第二个for循环中的goroutine刚执行一次,就被暂停执行其他的goroutine了),这是Go控制管理的

添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传