英文:
Go concurrency and channel confusion
问题
我是你的中文翻译助手,以下是你提供的代码的翻译:
我刚开始学习Go语言,对并发和通道的理解有些问题。
package main
import "fmt"
func display(msg string, c chan bool){
fmt.Println("显示第一条消息:", msg)
c <- true
}
func sum(c chan bool){
sum := 0
for i:=0; i < 10000000000; i++ {
sum++
}
fmt.Println(sum)
c <- true
}
func main(){
c := make(chan bool)
go display("hello", c)
go sum(c)
<-c
}
程序的输出结果是:
显示第一条消息:hello
10000000000
但是我原以为只会输出一行:
显示第一条消息:hello
所以在main
函数中,<-c
是阻塞的,它等待另外两个go
协程向通道发送数据。一旦main
函数从c
接收到数据,它应该继续执行并退出。
display
和sum
函数同时运行,sum
函数需要更长的时间,所以display
应该先向c
发送true
,然后程序在sum
完成之前退出。
我不确定我是否清楚地理解了这个问题。有人可以帮助我吗?谢谢!
英文:
I'm new to Go and have a problem understanding the concurrency and channel.
package main
import "fmt"
func display(msg string, c chan bool){
fmt.Println("display first message:", msg)
c <- true
}
func sum(c chan bool){
sum := 0
for i:=0; i < 10000000000; i++ {
sum++
}
fmt.Println(sum)
c <- true
}
func main(){
c := make(chan bool)
go display("hello", c)
go sum(c)
<-c
}
The output of the program is:
display first message: hello
10000000000
But I thought it should be only one line:
display first message: hello
So in the main function, <-c is blocking it and waits for the other two go rountines to send data to the channel. Once the main function receives the data from c, it should proceed and exit.
display and sum run simultaneously and sum takes longer so display should send true to c and the program should exit before sum finishes...
I'm not sure I understand it clearly. Could someone help me with this? Thank you!
答案1
得分: 4
你的程序的确切输出是未定义的,取决于调度器。调度器可以自由选择当前未被阻塞的所有goroutine之间进行切换。它通过非常短的时间间隔切换当前的goroutine,以使用户感觉所有事情都同时发生。除此之外,如果你的系统是多核的并且增加了runtime.GOMAXPROCS的值,调度器还可以在不同的CPU上并行执行多个goroutine。可能导致你的输出的一种情况是:
main
创建了两个goroutine- 调度器选择立即切换到其中一个新的goroutine,并选择
display
display
打印出消息,并被通道发送操作 (c <- true
) 阻塞,因为此时还没有接收者。- 调度器选择运行
sum
- 计算并打印出 sum 的结果
- 调度器选择不恢复
sum
goroutine(它已经使用了相当多的时间),继续执行display
display
将值发送到通道- 调度器选择运行 main
- main 退出,所有的goroutine都被销毁
但这只是一种可能的执行顺序。还有许多其他的执行顺序,其中一些会导致不同的输出。如果你想打印出第一个结果并在程序结束后退出,你应该使用一个 result chan string
,并将你的 main
函数改为打印 fmt.Println(<-result)
。
英文:
The exact output of your program is not defined and depends on the scheduler. The scheduler can choose freely between all goroutines that are currently not blocked. It tries to run those goroutines concurrently by switching the current goroutine in very short time intervals so that the user gets the feeling that everything happens simultanously. In addition to that, it can also execute more than one goroutine in parallel on different CPUs (if you happen to have a multicore system and increase runtime.GOMAXPROCS). One situation that might lead to your output is:
main
creates two goroutines- the scheduler chooses to switch to one of the new goroutines immediately and chooses
display
display
prints out the message and is blocked by the channel send (c <- true
) since there isn't a receiver yet.- the scheduler chooses to run
sum
next - the sum is computed and printed on the screen
- the scheduler chooses to not resume the
sum
goroutine (it has already used a fair amount of time) and continues withdisplay
display
sends the value to the channel- the scheduler chooses to run main next
- main quits and all goroutines are destroyed
But that is just one possible execution order. There are many others and some of them will lead to a different output. If you want to print just the first result and quit the program afterwards, you should probably use a result chan string
and change your main
function to print fmt.Println(<-result)
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论