gpt4 book ai didi

Golang 缓冲 channel 在发送之前接收数据

转载 作者:IT王子 更新时间:2023-10-29 02:27:04 25 4
gpt4 key购买 nike

我对 golang 很陌生。今天在测试 channel 在 Golang 中的工作方式时,我感到非常困惑。

根据教程:

Sends to a buffered channel block only when the buffer is full. Receives block when the buffer is empty.

我的测试程序是这样的:

package main

import "fmt"

func main() {
ch := make(chan int, 2)

go func(ch chan int) int {
for i := 0; i < 10; i++ {
fmt.Println("goroutine: GET ", <-ch)
}
return 1
}(ch)

for j := 0; j < 10; j++ {
ch <- j
fmt.Println("PUT into channel", j)
}
}

我得到这样的输出:

PUT into channel 0
PUT into channel 1
goroutine: GET 0
goroutine: GET 1
goroutine: GET 2
PUT into channel 2
PUT into channel 3
PUT into channel 4
PUT into channel 5
goroutine: GET 3
goroutine: GET 4
goroutine: GET 5
goroutine: GET 6
PUT into channel 6
PUT into channel 7
PUT into channel 8
PUT into channel 9

请注意,数字 2 是在放入 channel 之前从 channel 中获取的。为什么会这样?

最佳答案

事实并非如此。您的 Println("PUT into channel") 发生在您将它放入 channel 后,这意味着它有机会在执行打印语句之前从 channel 中读取.

示例输出中的实际执行顺序是:

  1. Writer 例程将 2 写入 channel 。
  2. Reader 例程从 channel 接收 2
  3. Reader 例程打印 goroutine: GET 2
  4. Writer 例程打印 PUT 到 channel 2

您对 channel 的读写操作按预期顺序进行,只是您的打印语句让它看起来乱序了。

如果您将编写器的操作顺序更改为:

    fmt.Println("PUT into channel", j)
ch <- j

您可能会看到更接近您预期的输出。但是,它仍然不一定完全代表操作顺序,因为:

  1. 执行是并发的,但写入 stdout 是同步的
  2. 每个函数调用和 channel 发送/接收都是调度程序切换的机会,因此即使以 GOMAXPROCS=1 运行,它也可以在打印和 channel 操作之间切换 goroutines(在阅读器中或作者)。

TL;DR:在记录并发操作时,不要过多地阅读日志消息的顺序。

关于Golang 缓冲 channel 在发送之前接收数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51769128/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com