英文:
Golang concurrency and blocking with a single channel, explanation needed
问题
我正在玩弄https://tour.golang.org/concurrency/5上提供的代码。我的想法是,通过摆脱quit通道,我可以简化代码,同时保持正确的程序行为-仅供学习目的。
这是我得到的代码(为了更好的可读性,我进一步简化了它):
package main
import "fmt"
import "time"
func sendNumbers(c chan int) {
for i := 0; i < 2; i++ {
c <- i
}
}
func main() {
c := make(chan int)
go func() {
for i := 0; i < 2; i++ {
fmt.Println(<-c)
}
}()
time.Sleep(0 * time.Second)
sendNumbers(c)
}
在这段代码中,我生成的goroutine应该能够在返回之前接收到2个数字。接下来,我调用的sendNumbers()函数会向通道c发送确切的2个数字。
因此,程序的预期输出是2行:0和1。然而,当我在页面上运行代码时,我得到的只是一个包含0的单行。
请注意,我在调用sendNumbers(c)之前故意添加的
time.Sleep(0 * time.Second)
如果我将其更改为
time.Sleep(1 * time.Second)
输出就会变成预期的:
0
1
所以,我对发生的事情感到困惑。有人能解释一下发生了什么吗?不管在调用sendNumbers()之前经过多长时间,发送和接收都不应该阻塞吗?
英文:
I'm playing around with the code presented on https://tour.golang.org/concurrency/5. My idea was that I could simplify the code by getting rid of the quit channel and still keep the correct program behavior - just for learning purposes.
Here is the code I've got (simplified it even more for better readability):
package main
import "fmt"
import "time"
func sendNumbers(c chan int) {
for i := 0; i < 2; i++ {
c <- i
}
}
func main() {
c := make(chan int)
go func() {
for i := 0; i < 2; i++ {
fmt.Println(<-c)
}
}()
time.Sleep(0 * time.Second)
sendNumbers(c)
}
In this code, the go routine I spawn should be able to receive 2 numbers before it returns. The sendNumbers() function I call next sends exactly 2 numbers to the channel c.
So, the expected output of the program is 2 lines: 0 and 1. However, what I'm getting when I run the code on the page, is just a single line containing 0.
Note the
time.Sleep(0 * time.Second)
though that I deliberately added before calling sendNumbers(c). If I change it to
time.Sleep(1 * time.Second)
The output becomes as expected:
0
1
So, I'm confused with what happens. Can someone explain what is going on? Shouldn't both sends and receives block regardless of how much time is passed before I call sendNumbers()?
答案1
得分: 2
在Go语言中,无论其他goroutine是否仍在运行,程序在主函数返回时都会退出。如果你想确保主函数不会过早退出,你需要一些同步机制。你可以使用同步原语来实现,也可以只使用通道来实现,后者可能是更符合惯例的方式。
参考链接:https://nathanleclaire.com/blog/2014/02/15/how-to-wait-for-all-goroutines-to-finish-executing-before-continuing/
英文:
In Go, the program exits as soon as the main function returns regardless of whether other goroutines are still running or not. If you want to make sure the main function does not exit prematurely, you need some synchronization mechanism. https://nathanleclaire.com/blog/2014/02/15/how-to-wait-for-all-goroutines-to-finish-executing-before-continuing/
<br>You don’t absolutely have to use synchronization primitives, you could also do it with channels only, arguably a more idiomatic way to do it.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论