我有 go 代码,它基本上同时运行两个 go 例程。其中一个从 (1-10) 发送 10 个 int 数字到缓冲通道“ch”(容量为 4),另一个 go 例程在for range loop package main import ( "fmt" "sync" "time" "runtime" ) func doSm(ch chan int, wg *sync.WaitGroup) { defer wg.Done() for i := 1; i <= 10; i++ { fmt.Println("sending", i) ch <- i fmt.Println("sent", i) } close(ch) } func doSm2(ch chan int, wg *sync.WaitGroup) { defer wg.Done() time.Sleep(5 * time.Second) for v := range ch { fmt.Println("result:", v) } } func main() { runtime.GOMAXPROCS(1) var wg sync.WaitGroup ch := make(chan int, 4) wg.Add(2) go doSm(ch, &wg) go doSm2(ch, &wg) wg.Wait() }该问题可以在下面的输出中找到。doSm() 通过 channel 发送 4 个 int 并且 go 调度程序阻塞 go 例程,直到 doSm2() 从 channel 读取这 4 个值。之后,缓冲区为空,doSm() 发送 1 个 int,doSm2() 立即读取它。现在,缓冲区再次为空,准备发送 4 个值。然而,doSm() 以某种方式发送了 5 个值(6、7、8、9、10),尽管它有容量。sending 1sent 1sending 2sent 2sending 3sent 3sending 4sent 4sending 5result: 1result: 2result: 3result: 4result: 5sent 5sending 6sent 6sending 7sent 7sending 8sent 8sending 9sent 9sending 10sent 10result: 6result: 7result: 8result: 9result: 10知道为什么会这样吗?还是我错过了什么?
2 回答

慕桂英546537
TA贡献1848条经验 获得超10个赞
举例说明。
result: 5
sent 5
sending 6
sent 6
sending 7
sent 7
sending 8
sent 8
sending 9
sent 9
sending 10
sent 10
result: 6
result 5被打印,然后我们看到sent 6-7-8-9-10,然后我们看到result 6打印。这并不意味着这些值6-7-8-9-10都在通道的缓冲区中(显然它们不是)。该值6已从通道接收,但后续fmt.Println()行尚未执行。但由于6接收到,缓冲区中只有 3 个数字,因此10可以在通道上发送,如输出所示。

烙印99
TA贡献1829条经验 获得超13个赞
这是一个可能导致此输出的执行:
发送 goroutine 发送 4 个值,并打印
发送 goroutine 块
接收 goroutine 接收一个值
发送 goroutine 发送另一个值并打印
接收 goroutine 打印
接收 goroutine 接收剩余的值
通过这种交错,看起来好像发送 goroutine 发送了 5 个值。
简而言之:当涉及多个 goroutines 时,打印到 stdout 可能不会显示 goroutines 的实际交错。
- 2 回答
- 0 关注
- 135 浏览
添加回答
举报
0/150
提交
取消