登录
首页 >  Golang >  Go问答

为什么这段Golang代码没有发生死锁情况?

来源:stackoverflow

时间:2024-02-16 09:57:23 385浏览 收藏

对于一个Golang开发者来说,牢固扎实的基础是十分重要的,golang学习网就来带大家一点点的掌握基础知识点。今天本篇文章带大家了解《为什么这段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 从 go-routine f1() 发送到的通道接收数据。 同样,没有 go-routine 发送到由 go-routine f2() 接收的通道。


解决方案


正如 @icza 的评论正确指出的那样,当所有 goroutine 都陷入困境并且无法取得进展时,就会发生死锁。在你的例子中, f1f2 被卡住了,但主 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

正如@icza所说,主goroutine可以继续并最终终止。

如果从两个函数调用中的任何一个中删除 go 关键字(使它们发生在主 goroutine 上),那么应用程序就会出现死锁。请参阅此演示(它为您突出显示了僵局)https://play.golang.org/p/r9qo2sc9LQA

终于介绍完啦!小伙伴们,这篇关于《为什么这段Golang代码没有发生死锁情况?》的介绍应该让你收获多多了吧!欢迎大家收藏或分享给更多需要学习的朋友吧~golang学习网公众号也会发布Golang相关知识,快来关注吧!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>