考虑以下Go代码片段:
c := make(chan string)
go func() {
time.Sleep(100 * time.Millisecond)
fmt.Println("Sending test1...")
c <- "test1"
fmt.Println("Sending test2...")
c <- "test2"
fmt.Println("Done sending")
}()
go func() {
for {
select {
case n := <-c:
fmt.Println("Received:", n)
}
}
}()
完整来源: http://play.golang.org/p/yY6JQzDMvn
我希望第一个goroutine会在尝试将"test1"
写入通道时阻塞,直到第二个goroutine中的接收为止。预期的输出是:
Sending test1...
Received: test1
Sending test2...
Received: test2
然而,当我实际运行该示例时,我最终得到:
Sending test1...
Sending test2...
Received: test1
Received: test2
输出会显示发送没有像预期的那样阻塞。这里发生了什么?
答案 0 :(得分:5)
这是由两个goroutines中的竞争条件引起的。默认情况下,Go运行时为所有goroutine使用单个线程,因此执行序列化。考虑执行上述代码的以下可能方案:
Sleep()
电话Sleep()
通话结束后继续执行"test1"
被写入阻止"Sending test2..."
并将第二个值写入再次阻止的通道"Received: test1"
消息总之,发送确实是阻塞的,它似乎并不是由于输出的顺序。