具有多个通道的多个 goroutine 的死锁
Deadlock with Multiple goroutines with multiple channels
我正在开发一个示例程序,使用多通道 goroutine 打印 1 到 100 之间的奇数之和和偶数之和。
你可以找到我的代码
输出
sum of even number = 2550
sum of odd number = 2500
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.print(0x434100, 0x11db7c)
/tmp/sandbox052575152/main.go:18 +0xc0
main.main()
/tmp/sandbox052575152/main.go:14 +0x120
代码有效,但存在死锁。
我不确定我的代码有什么问题
我们可以遍历通过通道发送的值。要打破这种迭代通道,需要明确关闭。否则 range 将以与 nil 通道相同的方式永远阻塞。在您的代码中,您没有关闭 sum
(用于打印功能 sumValues
频道)通道。这就是为什么以下功能将永远被阻止。
func print(sumValues <-chan string ){
for val := range sumValues {
fmt.Println(val)
}
}
所以你必须在doSum
函数中的所有go例程完成后关闭sum
函数中的sum
通道(否则sum
通道可能在 go 例程完成之前关闭)。您可以使用 sync.WaitGroup
来做到这一点。请参阅下面更新的 doSum
函数:
func doSum(sum chan<- string, oddChan <-chan int, evenChan <-chan int) {
var waitGroup sync.WaitGroup
waitGroup.Add(2) // Must wait for 2 calls to 'done' before moving on
go func(sum chan<- string) {
s1 := 0
for val := range oddChan {
s1 += val
}
sum <- fmt.Sprint("sum of odd number = ", s1)
waitGroup.Done()
}(sum)
go func(sum chan<- string) {
s1 := 0
for val := range evenChan {
s1 += val
}
sum <- fmt.Sprint("sum of even number = ", s1)
waitGroup.Done()
}(sum)
// Waiting for all goroutines to exit
waitGroup.Wait()
// all goroutines are complete now close the sum channel
close(sum)
}
我正在开发一个示例程序,使用多通道 goroutine 打印 1 到 100 之间的奇数之和和偶数之和。
你可以找到我的代码
输出
sum of even number = 2550
sum of odd number = 2500
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.print(0x434100, 0x11db7c)
/tmp/sandbox052575152/main.go:18 +0xc0
main.main()
/tmp/sandbox052575152/main.go:14 +0x120
代码有效,但存在死锁。 我不确定我的代码有什么问题
我们可以遍历通过通道发送的值。要打破这种迭代通道,需要明确关闭。否则 range 将以与 nil 通道相同的方式永远阻塞。在您的代码中,您没有关闭 sum
(用于打印功能 sumValues
频道)通道。这就是为什么以下功能将永远被阻止。
func print(sumValues <-chan string ){
for val := range sumValues {
fmt.Println(val)
}
}
所以你必须在doSum
函数中的所有go例程完成后关闭sum
函数中的sum
通道(否则sum
通道可能在 go 例程完成之前关闭)。您可以使用 sync.WaitGroup
来做到这一点。请参阅下面更新的 doSum
函数:
func doSum(sum chan<- string, oddChan <-chan int, evenChan <-chan int) {
var waitGroup sync.WaitGroup
waitGroup.Add(2) // Must wait for 2 calls to 'done' before moving on
go func(sum chan<- string) {
s1 := 0
for val := range oddChan {
s1 += val
}
sum <- fmt.Sprint("sum of odd number = ", s1)
waitGroup.Done()
}(sum)
go func(sum chan<- string) {
s1 := 0
for val := range evenChan {
s1 += val
}
sum <- fmt.Sprint("sum of even number = ", s1)
waitGroup.Done()
}(sum)
// Waiting for all goroutines to exit
waitGroup.Wait()
// all goroutines are complete now close the sum channel
close(sum)
}