为什么这会导致Go中出现死锁?

为什么这会导致Go中出现死锁?,go,deadlock,Go,Deadlock,这不是一个关于如何更好地写这篇文章的问题。这是一个关于Go为什么会在这个场景中导致死锁的问题 package main import "fmt" func main() { chan1 := make(chan bool) chan2 := make(chan bool) go func() { for { <-chan1 fmt.Printf("chan1\n") cha

这不是一个关于如何更好地写这篇文章的问题。这是一个关于Go为什么会在这个场景中导致死锁的问题

package main

import "fmt"

func main() {
    chan1 := make(chan bool)
    chan2 := make(chan bool)

    go func() {
        for {
            <-chan1
            fmt.Printf("chan1\n")
            chan2 <- true
        }
    }()

    go func() {
        for {
            <-chan2
            fmt.Printf("chan2\n")
            chan1 <- true
        }
    }()

    for {
        chan1 <- true
    }
}
为什么这不会导致无限循环?为什么它会在放弃之前做两次完整的“ping ping”(而不是一次)

goroutine 1 [chan send]:
goroutine 5 [chan send]:
goroutine 6 [chan send]:
这说明了一切:您所有的goroutine都被阻止,试图在另一端没有人接收的频道上发送


因此,您的第一个goroutine阻塞在
chan2上,看起来很复杂,但答案很简单

它将在以下情况下死锁:

  • 第一个例程正在尝试写入
    chan2
  • 第二个路由正在尝试写入
    通道1
  • Main正在尝试写入
    通道1
怎么会这样?例如:

  • 主写入
    chan1
    。在另一次写入时阻塞
  • 例行程序1:
    chan1
    接收来自Main的数据。印刷品。写
    通道2上的块
  • 例行程序2:
    chan2
    接收。印刷品。写入
    通道1上的块
  • 例行程序1:
    chan1
    从例行程序2接收。印刷品。写
    通道2上的块
  • 例行程序2:
    chan2
    接收。印刷品。写入
    通道1上的块
  • 主写入
    chan1
    。在另一次写入时阻塞
  • 例行程序1:
    chan1
    接收来自Main的数据。印刷品。写
    通道2上的块
  • 主写入
    chan1
    。在另一次写入时阻塞
目前所有例程都被阻止。i、 e:

例行程序1无法写入
通道2
,因为例行程序2未接收,但在尝试写入
通道1
时实际被阻止。但是没有人在听
频道1


正如@HectorJ所说,这完全取决于调度程序。但是在这种设置中,死锁是不可避免的。

从运行时的角度来看,您会遇到死锁,因为所有例程都试图发送到通道,而没有例程等待接收任何内容

但为什么会这样?我会给你们讲一个故事,因为我喜欢想象我遇到僵局时的例行程序

你有两名球员(常规)和一个球(
true
value)。每个球员都在等待一个球,一旦拿到球,他们就会把球传给另一个球员(通过通道)。这就是你的两个例程真正在做的事情,这确实会产生一个无限循环

问题是主循环中引入的第三个播放器。他躲在第二名球员后面,一旦他看到第一名球员双手空空,他就会向他扔另一个球。所以我们最后两个球员都拿着一个球,不能把球传给另一个球员,因为另一个球员手里已经有(第一个)球了。这个隐藏的、邪恶的球员还试图再传一个球。每个人都很困惑,因为有三个球,三个球员,没有空手


换句话说,你已经介绍了第三个打破游戏的玩家。他应该是一个裁判,在比赛开始的时候传球第一个球,看着球,但是不要再出球了!这意味着,在主例程中不应该有一个循环,而应该有一个简单的
chan1,这是有帮助和有意义的。因此,我将假设频道不可能有多个附加值——这意味着Go已经将goroutine视为“休眠”,而不仅仅是被频道屏蔽。它如何/为什么处于休眠状态?它被通道操作阻塞,无法解除阻塞。运行时检测到所有goroutine都处于阻塞状态,因此不会发生任何事件来解除阻塞其中任何一个goroutine。
goroutine 1 [chan send]:
goroutine 5 [chan send]:
goroutine 6 [chan send]:
chan1
chan2
chan1
chan2
chan1
chan2
chan1
chan2
chan1
chan2
chan1
chan2
chan1
fatal error: all goroutines are asleep - deadlock!