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

Concurrency 打印到标准输出会导致阻塞的goroutine运行吗?,concurrency,go,goroutine,Concurrency,Go,Goroutine,作为一个愚蠢的基本线程练习,我一直在尝试在golang中实现。有了频道,这应该很容易,但我遇到了海森堡。也就是说,当我尝试诊断时,问题消失了 考虑以下几点。main()函数将整数(或“客户”)推送到shop频道barber()阅读shop频道来剪“客户”的头发。如果我在customer()函数中插入fmt.Print语句,程序将按预期运行。否则,barber() 主程序包 输入“fmt” func客户(id int,shop chan添加runtime.GOMAXPROCS(2)在main的开头

作为一个愚蠢的基本线程练习,我一直在尝试在golang中实现。有了频道,这应该很容易,但我遇到了海森堡。也就是说,当我尝试诊断时,问题消失了

考虑以下几点。
main()
函数将整数(或“客户”)推送到
shop
频道
barber()
阅读
shop
频道来剪“客户”的头发。如果我在
customer()
函数中插入
fmt.Print
语句,程序将按预期运行。否则,
barber()

主程序包
输入“fmt”

func客户(id int,shop chan添加
runtime.GOMAXPROCS(2)
在main的开头解决了这个问题?

问题在于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:
    }
}

func客户(id int,如果go运行时只使用一个线程,则您的答案有效。通过运行时调用(如lazy1所说)或设置环境变量来设置GOMAXPROCS,也将允许任何goroutine在单独的线程上与其他goroutine并行运行。扩展您的答案以反映go的运行时方式可能值得一试在可用线程上多路复用goroutines。@MattJoiner您能详细说明一下吗?提高并行级别只会减少并发错误的出现。它们仍然存在。正确的代码应该可以工作,而不管GOMAXPROCS的值是多少。也许看一看Rob Pike的并发性不是并行性谈话可能会更清楚。