Go语言 为什么没有缓冲区的通道会导致此错误?[重复]

v9tzhpje  于 2023-02-14  发布在  Go
关注(0)|答案(2)|浏览(121)
    • 此问题在此处已有答案**:

Buffered/Unbuffered channel(3个答案)
fatal error: all goroutines are asleep - deadlock! when channel is not buffered(1个答案)
Why is the order of channels receiving causing/resolving a deadlock in Golang?(3个答案)
In the Go select construct, can I have send and receive to unbuffered channel in two case statements?(2个答案)
21小时前关闭。

package main

import (
    "fmt"
    "sync"
)

func main() {
    ch := make(chan struct{})

    wg := &sync.WaitGroup{}

    wg.Add(1)
    go func() {
        defer wg.Done()
        ch <- struct{}{}
    }()

    wg.Wait()

    <-ch

    fmt.Println("finished")
}
    • 结果**

已完成将打印

package main

import (
    "fmt"
    "sync"
)

func main() {
    ch := make(chan struct{}, 1)

    wg := &sync.WaitGroup{}

    wg.Add(1)
    go func() {
        defer wg.Done()
        ch <- struct{}{}
    }()

    wg.Wait()

    <-ch

    fmt.Println("finished")
}
    • 结果**完成后可立即打印

这两个代码之间的唯一区别是第一个代码使用无缓冲器通道,但第二个代码使用带缓冲器的通道
第一段代码中ch〈-struct {}{}无法运行,message无法发送到通道,为什么会出现这种情况,有没有官方的解释或者材料?

ca1c2owp

ca1c2owp1#

在第一个例子中,wg.Done()只能在通道上的值被发送之后被调用,但是由于通道是无缓冲的,所以发送只能在接收方准备好的情况下发生,main goroutine应该是接收方,但是它只能在wg.Wait()之后接收,但是wg.Wait()会阻塞直到wg.Done()被调用,所以这是一个死锁。
这在规范中:发送报表:
通信阻塞,直到发送可以继续。如果接收方准备就绪,则无缓冲通道上的发送可以继续。

xriantvc

xriantvc2#

使用非缓冲通道时,从通道发送或接收命令会阻塞
这意味着在非缓冲通道中,发送消息的go例程没有 done,因此它不会调用wg.Done(),这将使wg.Wait()方法保持阻塞状态。如果在播放服务器https://go.dev/play/p/oDpyL6-dARP上运行代码,它将死机并显示一条信息性消息:fatal error: all goroutines are asleep - deadlock!
当使用缓冲通道时,go例程运行,因为通道有缓冲区,然后调用wg.Done()wg.Done()随后释放wg.Wait()

相关问题