首页  >  文章  >  后端开发  >  Go 并发:为什么我的程序在使用通道时打印出意外的输出?

Go 并发:为什么我的程序在使用通道时打印出意外的输出?

DDD
DDD原创
2024-10-28 16:16:17905浏览

Go Concurrency: Why Does My Program Print Unexpected Output When Using Channels?

解决了 Go 并发和通道混乱

在 Go 中处理并发时,通道在 goroutine 之间的通信中发挥着关键作用。然而,它们的行为有时会导致混乱。

考虑以下 Go 程序:

<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>

程序的预期行为是打印“显示第一条消息:hello”,然后退出。然而,实际输出包括 sum 函数的结果:

display first message: hello
10000000000

解释

主 Goroutine 阻塞在该行上:

<code class="go"><-c</code>

这意味着主 Goroutine 在从通道 c 接收到值之前无法继续执行。 display 和 sum 都向 c 发送一个真值,这会解除主 goroutine 的阻塞。然而,调度器可以选择先运行哪个 goroutine。

可能的执行顺序:

  1. Main 创建两个 goroutine 用于显示和求和。
  2. 调度器运行 display首先,打印消息并在通道发送上阻塞。
  3. 调度程序切换到 sum goroutine。
  4. Sum 计算并打印结果。
  5. 调度程序恢复显示,向通道发送一个值。
  6. 主协程收到值后退出。

解决方案

确保程序只打印第一个结果,我们可以使用结果通道:

<code class="go">func display(msg string, result chan string) {
    result <- msg
}</code>

并将main函数更改为:

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

    go display("hello", result)
    fmt.Println(<-result)
}</code>

以上是Go 并发:为什么我的程序在使用通道时打印出意外的输出?的详细内容。更多信息请关注PHP中文网其他相关文章!

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