【发布时间】:2018-04-15 15:50:30
【问题描述】:
我正在尝试类似于以下模式的东西:
func sendFunc(n int, c chan int) {
for i := 0; i < n; i++ {
c <- i
fmt.Println("Pushed")
}
close(c)
}
func main() {
c := make(chan int, 10)
go sendFunc(10, c)
// Receive from the channel
for i := range c {
fmt.Println(i)
}
}
输出似乎是同步的,如下所示:
Pushed
Pushed
Pushed
Pushed
Pushed
Pushed
Pushed
Pushed
Pushed
Pushed
0
1
2
3
4
5
6
7
8
9
如果我将缓冲通道更改为非缓冲通道:
c := make(chan int)
结果似乎是异步的:
Pushed
0
1
Pushed
Pushed
2
3
Pushed
Pushed
4
5
Pushed
Pushed
6
7
Pushed
Pushed
8
9
Pushed
为什么它的行为不同?
更新
所以我的场景是:在接收器中,每次从生产者接收到新数据时都会发出一个请求,结果表明调度程序直到所有数据都发送到通道后才开始接收(给定一个缓冲的有足够空间的频道),除非生产者被暂停(例如通过调用time.sleep())。因此我最终使用了非缓冲通道,以便等待响应的时间和生产者中处理数据的时间可以重叠,从而提高并发性。
【问题讨论】:
-
你正在观察 goroutine 调度器的效果。在发送循环中添加 time.Sleep(time.Second) 并观察会发生什么。
-
我建议您运行 go trace 工具并可视化跟踪。它将帮助您了解两个 go 例程是如何运行的。有关如何使用跟踪工具stackoverflow.com/questions/32131339/the-go-1-5-trace-command,请参阅此答案