gpt4 book ai didi

concurrency - 打印到标准输出会导致阻塞的 goroutine 运行?

转载 作者:IT王子 更新时间:2023-10-29 01:14:43 26 4
gpt4 key购买 nike

作为一个愚蠢的基本线程练习,我一直在尝试实现 sleeping barber problem在戈朗。有了 channel ,这应该很容易,但我遇到了一个 heisenbug。也就是说,当我尝试对其进行诊断时,问题就消失了!

请考虑以下事项。 main() 函数将整数(或“客户”)推送到 shop channel 。 barber() 读取 shop channel 来剪“顾客”的头发。如果我将 fmt.Print 语句插入到 customer() 函数中,程序将按预期运行。否则,barber() 永远不会剪任何人的头发。

package main

import "fmt"

func customer(id int, shop chan<- int) {
// Enter shop if seats available, otherwise leave
// fmt.Println("Uncomment this line and the program works")
if len(shop) < cap(shop) {
shop <- id
}
}

func barber(shop <-chan int) {
// Cut hair of anyone who enters the shop
for {
fmt.Println("Barber cuts hair of customer", <-shop)
}
}

func main() {
shop := make(chan int, 5) // five seats available
go barber(shop)
for i := 0; ; i++ {
customer(i, shop)
}
}

知道发生了什么事吗?

最佳答案

问题在于 Go 调度程序的实现方式。只有在进行系统调用或阻塞 channel 操作时,当前 goroutine 才能让给其他 goroutine。 fmt.Println 进行系统调用,让 goroutine 有机会让步。否则它没有。

在实践中,这通常并不重要,但对于像这样的小问题,它有时会突然出现。

此外,在 channel 上进行非阻塞发送的一种更惯用、更简洁的方式是:

func customer(id int, shop chan<- int) {
// Enter shop if seats available, otherwise leave
select {
case shop <- id:
default:
}
}

按照您的操作方式,客户最终可能会在理发店外等候,因为在您实际发送时,len(shop) 可能已经更改。

关于concurrency - 打印到标准输出会导致阻塞的 goroutine 运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10150652/

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