我目前正在关注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)
第一个版本的代码产生死锁的根本原因是什么?
仅当有另一个 goroutine 从该通道读取数据时,写入无缓冲通道才会成功。在第一种情况下,只有一个 Goroutine(主 Goroutine)写入无缓冲的通道,并且没有其他 Goroutine 可以从中读取,因此这是一个死锁。
第二个有效,因为通道是缓冲的,通过填充缓冲区来写入成功。没有读取的第二次写入将会死锁。
第三个是有效的,因为写入发生在一个单独的 goroutine 中,该 goroutine 会等待第一个 goroutine 中的读取运行。