为了账号安全,请及时绑定邮箱和手机立即绑定

打印到stdout会导致阻塞的goroutine运行?

打印到stdout会导致阻塞的goroutine运行?

Go
慕容森 2021-04-30 09:10:49
作为一个愚蠢的基本线程练习,我一直在尝试在golang中实现睡眠理发师问题。使用通道,这应该很容易,但是我遇到了heisenbug。也就是说,当我尝试诊断时,问题消失了!考虑以下。该main()函数将整数(或“客户”)压入shop通道。barber()阅读shop频道来剪掉“顾客”的头发。如果我fmt.Print在customer()函数中插入一条语句,程序将按预期运行。否则,barber()切勿剪任何人的头发。package mainimport "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)    }}知道发生什么了吗?
查看完整描述

2 回答

?
青春有我

TA贡献1784条经验 获得超8个赞

问题是Go的调度程序的实现方式。当前的goroutine只有在进行系统调用或阻塞通道操作时才能屈服于其他goroutine。fmt.Println进行系统调用,使goroutine有机会屈服。否则它没有一个。


在实践中,这通常并不重要,但是对于诸如此类的小问题,有时可能会出现。


另外,在通道上进行非阻塞发送的一种更惯用,更省事的方法是:


func customer(id int, shop chan<- int) {

    // Enter shop if seats available, otherwise leave

    select {

    case shop <- id:

    default:

    }

}

这样做的方式是,客户可能最终在理发店外面等了,因为到您实际进行发送时,len(shop)可能已经改变了。


查看完整回答
反对 回复 2021-05-10
?
慕侠2389804

TA贡献1719条经验 获得超6个赞

runtime.GOMAXPROCS(2)在主开始处添加即可解决此问题吗?


查看完整回答
反对 回复 2021-05-10
  • 2 回答
  • 0 关注
  • 241 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信