我正在学习Go语言。有人可以在这里解释输出吗?
package main
import "fmt"
var c = make(chan int, 1)
func f() {
c <- 1
fmt.Println("In f()")
}
func main() {
go f()
c <- 2
fmt.Println(<-c)
fmt.Println(<-c)
}
输出:
In f()
2
1
Process finished with exit code 0
为什么“In f()”出现在“2”之前?如果在“2”之前打印“In f()”,则缓冲的 channel 应阻塞。但这没有发生,为什么?
其他输出是合理的。
Image of my confusing result
最佳答案
导致此情况发生的事件顺序如下:
2
写入 channel 。 channel 的容量现已耗尽。 1
写入 channel 。 导致此事件死锁的事件顺序如下:
1
写入 channel 。 channel 的容量现已耗尽。 2
写入 channel 。由于 channel 的缓冲区已满,因此将阻塞。 您提供的输出似乎表明goroutine首先完成,并且程序没有死锁,这与上述两种情况相矛盾。这是发生了什么:
2
写入 channel 。 2
。 1
写入 channel 。 In f()
。 2
。 1
。 1
。 请记住,除非您以编程方式实现它们,否则您对goroutine的调度没有任何保证。当您启动goroutine时,该goroutine的第一个代码实际执行时以及启动代码到此之前要执行的进度是不确定的。请注意,由于您的代码依赖于事件的特定顺序,因此该定义将其破坏,只是明确地说。
同样,在程序的任何时候,调度程序都可以决定在不同的goroutine之间进行切换。甚至单行
fmt.Printtln(<-c)
也包含多个步骤,并且在每个步骤之间都可以进行切换。
关于go - 为什么这个缓冲的 channel 在我的代码中没有阻塞?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59987856/