首页 >后端开发 >Golang >为什么 Go 程序会在给定代码片段中的消息之前打印计算总和,即使主 Goroutine 会阻塞直到从通道接收到信号?

为什么 Go 程序会在给定代码片段中的消息之前打印计算总和,即使主 Goroutine 会阻塞直到从通道接收到信号?

DDD
DDD原创
2024-10-29 21:49:29586浏览

Why does the Go program print the sum of the computation before the message in the given code snippet, even though the main goroutine blocks until a signal is received from the channel?

Go 并发和通道混乱

在 Go 中,并发允许使用 goroutine 并发执行多个任务。通道促进这些 goroutine 之间的通信。然而,理解并发性可能具有挑战性,尤其是在处理通道时。

考虑以下代码片段:

<code class="go">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
}</code>

在这段代码中,我们创建了两个 goroutine:display 和 sum。 display goroutine 打印一条消息,向通道发送信号,然后等待响应。 sum goroutine 执行长时间计算,打印结果,并向通道发送信号。在主 goroutine 中,我们会阻塞,直到从通道接收到信号。

代码的预期输出是:

display first message: hello

但是,我们观察到程序打印了两条消息以及计算总和:

display first message: hello
10000000000

理解问题

问题的出现是由于 goroutine 调度的不确定性。 Go 中的调度器在未被阻塞的 goroutine 之间自由选择。在此示例中,调度程序可以在任何给定时间执行任何 goroutine。

一种可能的执行顺序是:

  1. main 创建 goroutine。
  2. 调度器选择display,打印消息并等待响应。
  3. 调度器切换到sum,执行很长时间。
  4. 调度器切换回display,发送信号.
  5. 调度程序切换到 main,打印信号并退出。

在这种情况下,在显示器发送信号之前打印总和,导致意外的输出。

解决方案

为了确保程序只打印消息并在计算总和之前退出,我们可以使用不同的方法:

<code class="go">func main() {
    result := make(chan string)

    go display("hello", result)
    go sum(result)

    fmt.Println(<-result)
}</code>

在此修订版本中,结果通道携带单个值,即来自显示 goroutine 的消息。主 goroutine 现在打印来自通道的值,确保它在退出之前收到消息。

以上是为什么 Go 程序会在给定代码片段中的消息之前打印计算总和,即使主 Goroutine 会阻塞直到从通道接收到信号?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn