为什么这个缓冲通道没有在我的代码中阻塞?

伊万

我正在学习 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()”,则缓冲通道应阻塞。但这并没有发生,为什么呢?

其他输出是合理的。

我令人困惑的结果的图像

乌尔里希·埃克哈特

导致此运行的事件顺序如下:

  1. 触发 goroutine。
  2. 写到2频道。通道的容量现已耗尽。
  3. 从通道中读取并输出结果。
  4. 写到1频道。
  5. 从通道中读取并输出结果。

导致死锁的事件顺序如下:

  1. 触发 goroutine。
  2. 写到1频道。通道的容量现已耗尽。
  3. 写到2频道。由于通道的缓冲区已满,因此会阻塞。

您提供的输出似乎表明 goroutine 首先完成并且程序没有死锁,这与上述两种情况的解释相矛盾。但这就是发生的事情:

  1. 触发 goroutine。
  2. 写到2频道。
  3. 2从频道阅读
  4. 写到1频道。
  5. 输出In f()
  6. 输出2从通道接收到的。
  7. 1从频道阅读
  8. 输出1从通道接收到的。

请记住,除非您以编程方式强制执行,否则您对 goroutine 的调度没有任何保证。当您启动一个 goroutine 时,该 goroutine 的第一个代码何时实际执行以及启动代码在此之前的进度是不确定的。请注意,由于您的代码依赖于特定的事件顺序,因此它被该定义打破,只是明确地说。

此外,在程序中的任何时候,调度程序都可以决定在不同的 goroutine 之间切换。甚至单行也fmt.Printtln(<-c)包含多个步骤,并且在每个步骤之间可以发生切换。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

为什么将数据发送到没有缓冲的通道会阻塞执行例程

为什么我的代码在这个异步函数中没有等待输出?

为什么这个js代码中的值没有改变?

为什么我在这个div中没有滚动?

为什么goroutine中的未缓冲通道得到了这个顺序

为什么我的写入没有阻塞到此管道?

为什么我的代码没有进入这个适配器类?

为什么我用这个简单的代码没有收到段错误?

为什么当我输入这个 powershell 代码时它没有被执行?

Arduino IDE:“没有命名类型”,为什么我不能写这个代码?

在我的代码中读写文件是不阻塞的。为什么?

为什么我的代码没有在Entity Framework中更新?

为什么我的代码没有在 fortran 中编译?

为什么我的代码中的颜色值没有刷新?

为什么这个XPlot.Plotly代码没有编译>

为什么这个Ruby代码没有返回预期的答案?

为什么这个球拍代码没有终止?

为什么这个ruby代码没有引发异常?

为什么这个jquery代码没有执行?

为什么这个简单的代码没有运行 if only var

为什么我的代码没有递增?

为什么这个flutter代码应用程序中没有返回列表记录?

为什么这个while循环没有在下面的代码中结束?

为什么我没有缓冲区溢出?

为什么我的常量缓冲区没有更新?

为什么我的代码有这个错误

为什么在将这个无限循环添加到我的 javascript 代码后我的页面没有加载?

为什么我没有被警告这个问题?

为什么我的 angular 指令没有引入这个属性?