首页 >后端开发 >Golang >为什么Go的无缓冲通道的输出顺序是不确定的?

为什么Go的无缓冲通道的输出顺序是不确定的?

DDD
DDD原创
2024-12-07 11:03:12278浏览

Why is the output order of Go's unbuffered channels non-deterministic?

Golang 通道输出顺序:深入探究

在 Go 中理解从通道接收消息的顺序可能有点棘手。让我们深入研究您提供的代码:

func main() {
  messages := make(chan string)
  go func() { messages <- "hello" }()
  go func() { messages <- "ping" }()
  msg := <-messages
  msg2 := <-messages
  fmt.Println(msg)
  fmt.Println(msg2)
}

以下解释解决了您的担忧,并提供了对正在发生的情况的更清晰的理解:

首先,了解阻塞操作非常重要,例如从无缓冲通道发送或接收,不保证顺序。在 Go 中,goroutine 的执行是并发的,默认情况下没有定义 goroutine 的执行顺序。

当第一个 goroutine 尝试向通道发送“hello”时,如果当前没有接收者在等待,则该 goroutine被阻止。类似地,当第二个 goroutine 尝试发送“ping”时,它也会被阻塞。

现在,当到达 msg := <-messages 语句时,程序将任意解锁其中一个被阻塞的 goroutine。未阻塞的 goroutine 发送的消息将被接收到 msg 中。

msg2 :=

goroutine 解除阻塞并将其消息传输到 messages 中的顺序是不确定的。这就是为什么你总是看到“ping”在“hello”之前打印,即使你的假设是例程应该交替执行。

要确认这一点,你可以尝试向 goroutine 添加 print 语句:

func main() {
  messages := make(chan string)
  go func() {
    fmt.Println("Sending 'hello'")
    messages <- "hello"
    fmt.Println("Sent 'hello'")
  }()
  go func() {
    fmt.Println("Sending 'ping'")
    messages <- "ping"
    fmt.Println("Sent 'ping'")
  }()
  msg := <-messages
  msg2 := <-messages
  fmt.Println(msg)
  fmt.Println(msg2)
}

多次执行代码后,您会注意到 goroutine 中打印语句的顺序可能会有所不同。这进一步证明了 goroutine 执行的非确定性。

总而言之,在无缓冲通道中,无法保证通道输出的顺序,并且取决于相应 goroutine 被解除阻塞的顺序。

以上是为什么Go的无缓冲通道的输出顺序是不确定的?的详细内容。更多信息请关注PHP中文网其他相关文章!

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