gpt4 book ai didi

go - 解决 goroutines 死锁

转载 作者:IT王子 更新时间:2023-10-29 01:16:20 28 4
gpt4 key购买 nike

我一直在尝试解决我在 Golang 并发中遇到的这个简单问题。我一直在搜索所有可能的解决方案,但没有发现任何特定于我的问题(或者我可能会错过一个)。这是我的代码:

package main

import (
"fmt"
"time"
)

func producer(ch chan int, d time.Duration, num int) {

for i:=0; i<num; i++ {
ch <- i
time.Sleep(d)
}
}

func main() {
ch := make(chan int)

go producer(ch, 100*time.Millisecond, 2)
go producer(ch, 200*time.Millisecond, 5)

for {
fmt.Println(<-ch)
}

close(ch)
}

它打印错误:

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]: main.main() D:/Code/go/src/testconcurrency/main.go:23 +0xca exit status 2

避免此错误的有效方法是什么?谢谢。

最佳答案

你有生产者是“短暂的”,他们只在有限的时间内在 channel 上发送值,并且你有一个无休止的 for 循环,它无休止地从 channel 接收值,没有终止条件, channel 仅在此无限循环后关闭。一旦生产者停止发送值,就会陷入僵局。

channel 必须由生产者关闭,表明不再有任何值被发送到它上面。由于你有多个不同步的生产者(生产者之间不同步),一般你无法判断哪个先完成,所以你不能指定一个关闭 channel (而且一个 channel 只能关闭一次,参见 Why Go's channel can close twice? ;和 Closing channel of unknown length )。

你必须“协调”生产者,当所有生产者都完成工作后,协调者应该关闭 channel 。

并且消费者应该在 channel 上使用 for range,因为 for range 结构会接收 channel 关闭前发送的所有值,然后它自动终止。

对于协调,建议使用 sync.WaitGroup .在这种情况下是使用全局的还是本地的并将其传递给生产者取决于您。使用本地将使解决方案更通用且更易于扩展。需要注意的一件事是您必须传递一个指向 sync.WaitGroup 的指针。每当你启动一个新的生产者时,使用 WaitGroup.Add() 增加 WaitGroup 。 .当生产者完成后,它可以使用 WaitGroup.Done() 发出信号,最好使用 defer (这样它无论如何都会运行,在异常情况下缓解死锁)。 Controller 可以等待所有生产者使用完WaitGroup.Wait()。 .

这是一个完整的解决方案:

func producer(ch chan int, d time.Duration, num int, wg *sync.WaitGroup) {
defer wg.Done()

for i := 0; i < num; i++ {
ch <- i
time.Sleep(d)
}
}

func main() {
wg := &sync.WaitGroup{}
ch := make(chan int)

wg.Add(1)
go producer(ch, 100*time.Millisecond, 2, wg)
wg.Add(1)
go producer(ch, 200*time.Millisecond, 5, wg)

go func() {
wg.Wait()
close(ch)
}()

for v := range ch {
fmt.Println(v)
}
}

输出(在 Go Playground 上尝试):

0
0
1
1
2
3
4

参见相关问题:Prevent the main() function from terminating before goroutines finish in Golang

关于go - 解决 goroutines 死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48865561/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com