- 此问题在此处已有答案**:
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无法发送到通道,为什么会出现这种情况,有没有官方的解释或者材料?
2条答案
按热度按时间ca1c2owp1#
在第一个例子中,
wg.Done()
只能在通道上的值被发送之后被调用,但是由于通道是无缓冲的,所以发送只能在接收方准备好的情况下发生,main
goroutine应该是接收方,但是它只能在wg.Wait()
之后接收,但是wg.Wait()
会阻塞直到wg.Done()
被调用,所以这是一个死锁。这在规范中:发送报表:
通信阻塞,直到发送可以继续。如果接收方准备就绪,则无缓冲通道上的发送可以继续。
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()
。