初学Go语言,对channel、并发的疑问
初学go语言,对channel、并发感觉不太好理解。希望高人指点下。
下面的代码是我看到一本书上的,就是讲解channel的。
package main
import (
"fmt"
"math/rand"
)
func test(ch chan int, i int) {
ch <- rand.Int()
fmt.Println(i, "go...")
}
func main() {
chs := make([]chan int, 10)
for i := 0; i < 10; i++ {
chs[i] = make(chan int)
go test(chs[i], i)
}
for _, ch := range chs {
value := <-ch
fmt.Println(value)
}
var i int
fmt.Scan(&i)
fmt.Println("done")
}
这个程序的输出是
0 go...
134020434
1597969999
1721070109
2068675587
1237770961
220031192
2031484958
583324308
958990240
413002649
1 go...
2 go...
3 go...
4 go...
5 go...
6 go...
7 go...
8 go...
9 go...
我的疑惑是,为什么第一个打印出来的是0 go...?
我想来想去还觉得应该是先输出随机数,然后才输出0 go..., 1 go..., 2 go..., .........呀。
如果先打印了0 go...,那么后面的1 go...,2 go...不是也应该和随机数间隔打印出来吗?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
没看明白啥意思, 默认go是单线程运行的, 你设下gomaxprocs试试看
写并发要注意的一点就是,不要考虑先后的问题,因为这和系统底层调度有关。上层代码要关注的问题是同步和死锁。
根据输出结果,我们也可以大概猜测一下它的运行机制:
main 里有两个循环,当第一个循环运行结束后,第一个生成的test 也运行完毕了,所以会输出 "0 go"。 "<-" 操作在返回时相对耗时一些,所以会导致之后的结果 "* go" 会堆在后面。
并行可能不是顺序的,但也可能是打印的原因,可以先把channel接收的结果缓冲到结构中最后再打印
package main
import (
)
func test(ch chan int, i int) {
}
func main() {
}
在goroutine中执行的代码,可能在任何一个语句后被调度。在test里向channel里塞数据,这个也是会被调度的,而且一定会被调度,因为你的channel没有buffer。所以channel一塞数据,调度到main去取数据。main取完数据,鬼知道它又会调度到哪个goroutine去执行。按你的输出,又调度到了塞数据的那个goroutine执行了。所以先打印出0 go也是可以的。后面的,可能就是塞完数据就一直阻塞,等value都打印完,才调度回去打印k go
并行的东西,怎么说得准的呢?每次执行的结果都是不一定的!