有人可以解释为什么在对没有指示缓冲区大小的通道进行回复时出现死锁吗?
以这种方式创建确认频道时,我的测试陷入僵局;
这个僵局:deadlock
request := RequestMessage{
Value: "make it rain",
Confirm: make(chan *ReplyMessage),
}
但不是这样创建的;
这个不会死锁:no deadlock
request := RequestMessage{
Value: "make it rain",
Confirm: make(chan *ReplyMessage,1),
}
package main
import (
"fmt"
"sync"
)
type ReplyMessage struct {
Value string
}
type RequestMessage struct {
Value string
Confirm chan *ReplyMessage
}
var requestChannel chan *RequestMessage
func main() {
requestChannel = make(chan *RequestMessage, 10) // 8 is channel buffer size
request := RequestMessage{
Value: "make it rain",
Confirm: make(chan *ReplyMessage),
}
requestChannel <- &request
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done() // invoke Done on the WaitGroup when finished
request := <-requestChannel
fmt.Printf("Got Request: %s\n", request.Value)
reply := ReplyMessage{Value: "hi"}
request.Confirm <- &reply
}()
wg.Wait()
reply := <-request.Confirm
fmt.Println(reply.Value)
}
答案 0 :(得分:1)
您会陷入僵局,因为如果没有缓冲,请确认没有读取器,所以发送操作将阻塞。同时,您正在等待goroutine在主程序中返回(wg.Wait()
语句)。因此main和goroutine都被阻止了。
使用缓冲的chan可以使goroutine完成发送操作并退出,因此wg.Wait()
语句成功,之后继续执行主要操作。
一种解决无缓冲chan情况的方法是更改您等待goroutine完成的位置,即
reply := <-request.Confirm
fmt.Println(reply.Value)
wg.Wait()
在阻塞主机之前,您不会从chan中读取死锁,因此可以使goroutine退出。