与 GO 等待组同步

Synchronizing with a GO waitgroup

为什么这在示例 1 中是死锁,而在示例 2 中既不死锁也不打印任何内容?

示例 1.)

func main() {

    w := sync.WaitGroup{}
    w.Add(4)
    c := make(chan int)

    go func() { c <- 1; w.Done() }()
    go func() { c <- 2; w.Done() }()
    go func() { c <- 3; w.Done() }()

    go func() { println(len(c)); w.Done() }()

    w.Wait()
}

示例 2.)

func main() {
    w := sync.WaitGroup{}
    w.Add(3)
    c := make(chan int)

    go func() { c <- 1; w.Done() }()
    go func() { c <- 2; w.Done() }()
    go func() { c <- 3; w.Done() }()

    go func() { w.Wait(); println(len(c)) }()
}

您的第一个示例启动了 3 个 goroutine,每个 goroutine 都尝试在 c 无缓冲通道上发送一个值。由于没有人从通道接收,所有这些都会阻塞。所以等待他们完成的 main() 也会被阻塞。所有 goroutine 都被阻塞:deadlock.

在您的第二个示例中,main() 函数“只是”启动 goroutine,之后不执行任何操作。当 main goroutine 完成时(当你的 main() 函数 returns 时),你的应用程序也会结束,它不会等待其他非 main goroutines 完成。有关详细信息,请参阅

在第一个示例中,通道将无法发送,因为未缓冲通道的另一端没有接收器。发送的将永远阻塞。因此等待组将永远等待。这是一个死锁情况,因为您的程序根本无法继续。

在第二种情况下,同样的事情发生了,但是你在一个单独的 goroutine 中等待。所以主要功能是能够继续。这不是一个完全的僵局。在这种情况下,继续意味着程序只是存在。