go - golang:为什么这段代码没有死锁?
问题描述
golang:为什么这段代码没有死锁?
请通过以下代码:
package main
import (
"fmt"
"time"
)
func f1(done chan bool) {
done <- true
fmt.Printf("this's f1() goroutine\n")
}
func f2(done chan bool) {
val := <-done
fmt.Printf("this's f2() goroutine. val: %t\n", val)
}
func main() {
done1 := make(chan bool)
done2 := make(chan bool)
go f1(done1)
go f2(done2)
fmt.Printf("main() go-routine is waiting to see deadlock.\n")
time.Sleep(5 * time.Second)
}
如您所见,go-routine f1() 正在向通道发送一个值。go-routine f2() 正在从一个通道接收一个值。但是,没有从 go-routine f1() 发送到的通道接收 go-routine。同样,没有 go-routine 发送到 go-routine f2() 正在接收的通道上。
解决方案
正如@icza 的评论正确指出的那样,当所有goroutine 都卡住并且无法取得进展时,就会发生死锁。在您的情况下f1
并被f2
卡住,但主 goroutine 不是 - 所以这不是死锁。
但是,这是一个 goroutine 泄漏!当某些代码完成其逻辑存在但让 goroutine 运行(未终止)时,就会发生 Goroutine 泄漏。我发现了类似github.com/fortytw2/leaktest
用于检测 goroutine 泄漏的工具,它可以检测代码中的问题 - 试一试。
这是一个修改后的代码示例:
import (
"testing"
"time"
"github.com/fortytw2/leaktest"
)
func f1(done chan bool) {
done <- true
fmt.Printf("this's f1() goroutine\n")
}
func f2(done chan bool) {
val := <-done
fmt.Printf("this's f2() goroutine. val: %t\n", val)
}
func TestTwoGoroutines(t *testing.T) {
defer leaktest.CheckTimeout(t, time.Second)()
done1 := make(chan bool)
done2 := make(chan bool)
go f1(done1)
go f2(done2)
}
当您运行此测试时,您会看到如下内容:
--- FAIL: TestTwoGoroutines (1.03s)
leaktest.go:132: leaktest: timed out checking goroutines
leaktest.go:150: leaktest: leaked goroutine: goroutine 7 [chan send]:
leaktest-samples.f1(0xc000016420)
leaktest-samples/leaktest1_test.go:45 +0x37
created by leaktest-samples.TestTwoGoroutines
leaktest-samples/leaktest1_test.go:60 +0xd1
leaktest.go:150: leaktest: leaked goroutine: goroutine 8 [chan receive]:
leaktest-samples.f2(0xc000016480)
leaktest-samples/leaktest1_test.go:50 +0x3e
created by leaktest-samples.TestTwoGoroutines
leaktest-samples/leaktest1_test.go:61 +0xf3
推荐阅读
- java - 为什么我的应用会抛出空指针异常?
- r - DBI SQL Server ODBC 连接中返回的数据库对象缺少字母
- linux - 如何使用 ipcalc 在 Bash 脚本中验证 IP?
- javascript - 如何从地图函数返回数据
- c# - 使用 XMLSerializer 在 WPF 应用程序中读取/保存设置文件
- r - 使用多个类别的 R 数据绘制图时遇到问题
- c - 添加两行并将总和存储在最后一行
- python-3.x - 如何使用 matplotlib plt.imshow 更改热图的 y 刻度标签?
- database - 如何在测试中模拟数据库
- backbone.js - Backbone.js:使用 RESTful API 时视图不会呈现