根据此处的定义,死锁与资源争用有关。
在操作系统中,当一个进程或线程进入等待状态时会发生死锁,因为所请求的系统资源被另一个等待进程持有,而另一个等待进程又在等待另一个等待进程持有的另一个资源。如果一个进程不能无限期地改变它的状态,因为它请求的资源正在被另一个等待的进程使用,那么系统就被称为死锁。
在下面的代码中:
package main
import "fmt"
func main() {
c := make(chan string)
c <- "John"
fmt.Println("main() stopped")
}
main()go-routine 阻塞,直到任何其他 go-routine(没有这样)从该通道读取相同的数据。
但输出显示:
$ 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 也被阻塞在通道上,不是所有的 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()不应该退出,因为通道资源被任何一个 go-routine 使用。
为什么通道上的 go-routine 阻塞被认为是死锁?