非缓冲通道上的死锁
deadlock on not buffered channel
我目前正在学习 tour of go 教程并进入频道部分,因为我正在做一些测试,我发现了一个我很难理解的奇怪行为
以下代码产生死锁错误
package main
import "fmt"
func main() {
c := make(chan string)
c <- "test"
fmt.Printf("%v", <- c)
}
但执行以下操作之一可以修复代码
使用缓冲通道:
package main
import "fmt"
func main() {
c := make(chan string, 1)
c <- "test"
fmt.Printf("%v", <- c)
}
或将值设置为不同线程上的通道
package main
import "fmt"
func main() {
c := make(chan string)
go func(){c <- "test"}()
fmt.Printf("%v", <- c)
}
第一版代码产生死锁的根本原因是什么?
只有当有另一个 goroutine 从该通道读取数据时,写入无缓冲通道才会成功。在第一种情况下,你只有一个 goroutine,主 goroutine,它写入一个无缓冲的通道,没有其他 goroutine 可以从它读取,所以这是一个死锁。
第二个可以,因为channel有缓冲,填充buffer写入成功。没有读取的第二次写入将死锁。
第三个可行,因为写入发生在一个单独的 goroutine 中,它会等到第一个 goroutine 中的读取运行。
由于通道没有缓冲区,c <- "test"
将阻塞直到从 c 读取数据。由于 reader 在写入之后出现,因此它永远不会达到读取和死锁。
如果通道有缓冲区,c <- "test"
写入缓冲区而不必等待 reader。 reader 然后从通道缓冲区中读取。
这是因为 reader 和 writer 在同一个 goroutine 中,所以必须一个接一个地执行语句。如果 reader 和 writer 在不同的 goroutine 中,writer goroutine 可以阻塞直到 reader goroutine 读取。因此,通常不需要缓冲区。
我目前正在学习 tour of go 教程并进入频道部分,因为我正在做一些测试,我发现了一个我很难理解的奇怪行为
以下代码产生死锁错误
package main
import "fmt"
func main() {
c := make(chan string)
c <- "test"
fmt.Printf("%v", <- c)
}
但执行以下操作之一可以修复代码
使用缓冲通道:
package main
import "fmt"
func main() {
c := make(chan string, 1)
c <- "test"
fmt.Printf("%v", <- c)
}
或将值设置为不同线程上的通道
package main
import "fmt"
func main() {
c := make(chan string)
go func(){c <- "test"}()
fmt.Printf("%v", <- c)
}
第一版代码产生死锁的根本原因是什么?
只有当有另一个 goroutine 从该通道读取数据时,写入无缓冲通道才会成功。在第一种情况下,你只有一个 goroutine,主 goroutine,它写入一个无缓冲的通道,没有其他 goroutine 可以从它读取,所以这是一个死锁。
第二个可以,因为channel有缓冲,填充buffer写入成功。没有读取的第二次写入将死锁。
第三个可行,因为写入发生在一个单独的 goroutine 中,它会等到第一个 goroutine 中的读取运行。
由于通道没有缓冲区,c <- "test"
将阻塞直到从 c 读取数据。由于 reader 在写入之后出现,因此它永远不会达到读取和死锁。
如果通道有缓冲区,c <- "test"
写入缓冲区而不必等待 reader。 reader 然后从通道缓冲区中读取。
这是因为 reader 和 writer 在同一个 goroutine 中,所以必须一个接一个地执行语句。如果 reader 和 writer 在不同的 goroutine 中,writer goroutine 可以阻塞直到 reader goroutine 读取。因此,通常不需要缓冲区。