无缓冲通道上的死锁

Dav*_*rez 1 channel go

我目前正在关注go教程,并进入了有关通道的部分,当我进行一些测试时,我发现了一个我很难理解的奇怪行为

以下代码会产生死锁错误

package main

import "fmt"

func main() {
    c := make(chan string)
    c <- "test"
    fmt.Printf("%v", <- c)
}
Run Code Online (Sandbox Code Playgroud)

但执行以下操作之一可以修复代码

使用缓冲通道:

package main

import "fmt"

func main() {
    c := make(chan string, 1)
    c <- "test"
    fmt.Printf("%v", <- c)
}
Run Code Online (Sandbox Code Playgroud)

或将值设置为不同线程上的通道

package main

import "fmt"

func main() {
    c := make(chan string)
    go func(){c <- "test"}()
    fmt.Printf("%v", <- c)
}
Run Code Online (Sandbox Code Playgroud)

第一个版本的代码产生死锁的根本原因是什么?

Bur*_*dar 7

仅当有另一个 goroutine 从该通道读取数据时,写入无缓冲通道才会成功。在第一种情况下,只有一个 Goroutine(主 Goroutine)写入无缓冲的通道,并且没有其他 Goroutine 可以从中读取,因此这是一个死锁。

第二个有效,因为通道是缓冲的,通过填充缓冲区来写入成功。没有读取的第二次写入将会死锁。

第三个是有效的,因为写入发生在一个单独的 goroutine 中,该 goroutine 会等待第一个 goroutine 中的读取运行。