gpt4 book ai didi

go - 为什么 channel 上的 go-routine block 被认为是死锁?

转载 作者:行者123 更新时间:2023-12-01 22:42:29 25 4
gpt4 key购买 nike

根据定义here ,死锁与资源争用有关。

在操作系统中,当一个进程或线程进入等待状态时就会发生死锁,因为请求的系统资源被另一个等待进程占用,而另一个等待进程又在等待另一个等待进程占用的另一个资源。如果一个进程不能无限期地改变它的状态,因为它请求的资源正被另一个等待的进程使用,那么系统就被称为死锁。

在下面的代码中:

package main

import "fmt"

func main() {
c := make(chan string)

c <- "John"
fmt.Println("main() stopped")

}
main() go-routine 阻塞,直到任何其他 go-routine(没有这样)从该 channel 读取相同的数据。

但输出显示:
$ bin/cs61a 
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan send]:
main.main()
/home/user/../myhub/cs61a/Main.go:8 +0x54
$

编辑:

要点:“主 goroutine 被阻塞,因此所有 goroutine 都被阻塞,因此这是一个死锁。”在下面的代码中,非主 goroutine 也被阻塞在 channel 上,不是所有的 goroutine 都应该被阻塞吗?
package main

import (
"fmt"
"time"
)

func makeRandom(randoms chan int) {
var ch chan int
fmt.Printf("print 1\n")
<-ch
fmt.Printf("print 2\n")
}

func main() {

randoms := make(chan int)

go makeRandom(randoms)


}

编辑 2:

对于您在回答中的观点:“并非所有的 goroutine 都被阻塞,所以这不是死锁”。在下面的代码中,只有 main() goroutine 被阻塞,但不是 worker() :
package main

import (
"fmt"
)

func worker() {

fmt.Printf("some work\n")

}

func main() {

ch := make(chan int)

go worker()
<-ch

}

并且输出显示死锁:
$ bin/cs61a 
some work
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
main.main()
/home/user/code/src/github.com/myhub/cs61a/Main.go:18 +0x6f
$

理想情况下 main()不应该退出,因为 channel 资源被任何一个 go-routine 使用。

为什么 channel 上的 go-routine 阻塞被认为是死锁?

最佳答案

在 Go 中,死锁是指所有现有的 goroutine 都被阻塞。

您的示例有一个 goroutine(主 goroutine)被阻塞,因此所有 goroutine 都被阻塞,因此这是一个死锁。

注意:由于所有的 goroutines 都被阻塞,新的 goroutines 不会(不能)被启动(因为它们只能从正在运行的 goroutines 启动)。如果所有的 goroutine 都被阻塞并且不能做任何事情,那么永远等待是没有意义的。所以运行时退出。

编辑:

您在 main 中使用 sleep 的编辑代码与此重复:Go channel deadlock is not happening .基本上 sleep 不是永久阻塞操作( sleep 持续时间是有限的),因此在死锁检测中不考虑 goroutine sleep 。

编辑#2:

从那时起,您删除了 sleep()但它不会改变任何东西。你有 2 个 goroutine:main和执行 makeRandom() 的那个. makeRandom()被阻止和main()不是。所以并不是所有的 goroutine 都被阻塞了,所以这不是死锁。

编辑#3:

在您的最后一个示例中,当运行时检测到死锁时,只有一个 goroutine 仍在运行:main() .确实,您启动了一个执行 worker() 的 goroutine ,但这只会打印文本并终止。 “过去”的 goroutine 不算数,终止的 goroutine 也无法改变现有 goroutine 的阻塞状态。只有现有的 goroutine 才算。

关于go - 为什么 channel 上的 go-routine block 被认为是死锁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61759204/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com