致命错误 – 所有 Goroutine 都处于休眠状态!死锁

huangapple go评论81阅读模式
英文:

Fatal Error - All Goroutines are asleep! Deadlock

问题

我很困惑为什么这段代码会发生死锁。我收到一个关于goroutine处于休眠状态的致命错误。我使用了一个waitgroup来同步和等待goroutine完成,同时传递了我创建的waitgroup的地址而不是复制。我尝试过有和没有缓冲区,但问题仍然存在。

package main

import (
	"fmt"
	"sync"
)

func findMax(nums []int32) int32 {
	max := nums[0]
	for _, n := range nums {
		if n > max {
			max = n
		}
	}
	return max
}

func findFreq(nums []int32, n int32) int32 {
	mp := make(map[int32]int32)
	for _, num := range nums {
		if _, ok := mp[num]; ok {
			mp[num] += 1
		} else {
			mp[num] = 1
		}
	}
	if f, ok := mp[n]; ok {
		return f
	} else {
		return -1
	}
}

func performWork(ch chan int32, nums []int32, q int32, wg *sync.WaitGroup) {
	defer wg.Done()
	seg := nums[q-1:]
	max := findMax(seg)
	freq := findFreq(seg, max)
	ch <- freq
}

func frequencyOfMaxValue(numbers []int32, q []int32) []int32 {
	res := []int32{}
	var wg sync.WaitGroup
	ch := make(chan int32)

	for _, query := range q {
		wg.Add(1)
		go performWork(ch, numbers, query, &wg)
	}
	wg.Wait()
	close(ch)
	for n := range ch {
		res = append(res, n)
	}
	return res
}

func main() {
	nums := []int32{5, 4, 5, 3, 2}
	queries := []int32{1, 2, 3, 4, 5}
	fmt.Println(frequencyOfMaxValue(nums, queries))
}
英文:

I'm confused as to why this code deadlocks. I'm getting a fatal error about the goroutines being asleep. I'm using a waitgroup to synchronize and wait for the goroutines to finish, as well as passing the address of the one waitgroup I created instead of copying. I tried with and without a buffer but still.

package main
import (
&quot;fmt&quot;
&quot;sync&quot;
)
func findMax(nums []int32) int32{
max:=nums[0]
for _, n := range nums{
if n &gt; max{
max = n
}
}
return max
}
func findFreq(nums []int32,  n int32) int32{
mp := make(map[int32]int32)
for _, num := range nums{
if _, ok := mp[num]; ok{
mp[num]+=1
}else{
mp[num]=1
}
}
if f, ok := mp[n]; ok{
return f
}else{
return -1
}
}
func performWork(ch chan int32, nums []int32, q int32, wg *sync.WaitGroup){
defer wg.Done()
seg:=nums[q-1:]
max:=findMax(seg)
freq:=findFreq(seg, max)
ch &lt;- freq
}
func frequencyOfMaxValue(numbers []int32, q []int32) []int32 {
res := []int32{}
var wg sync.WaitGroup
ch := make(chan int32)
for _, query := range q{
wg.Add(1)
go performWork(ch, numbers, query, &amp;wg)
}
wg.Wait()
for n := range ch{
res=append(res, n)
}
return res
}
func main() {
nums := []int32{5,4,5,3,2}
queries:=[]int32{1,2,3,4,5}
fmt.Println(frequencyOfMaxValue(nums,queries))
}

答案1

得分: 3

工人们被阻塞,等待主 goroutine 在通道上接收。主 goroutine 被阻塞,等待工人们完成。死锁!

假设你成功解决了这个死锁问题,还会遇到另一个死锁。主 goroutine 在一个循环中从 ch 接收数据,但没有任何地方关闭 ch

通过运行另一个 goroutine,在工人们完成工作后关闭通道来解决死锁问题。

for _, query := range q {
	wg.Add(1)
	go performWork(ch, numbers, query, &wg)
}

go func() {
	wg.Wait() // <-- 等待工人们完成
	close(ch) // <-- 导致主 goroutine 跳出 ch 的循环
}()

for n := range ch {
	res = append(res, n)
}
英文:

The workers are blocked waiting for main goroutine to receive on the channel. The main goroutine is blocked waiting for the workers to complete. Deadlock!

Assuming that you get past this deadlock, there's another deadlock. The main goroutine receives on ch in a loop, but nothing closes ch.

Remove the deadlocks by running another goroutine to close the channel when the workers are done.

for _, query := range q {
wg.Add(1)
go performWork(ch, numbers, query, &amp;wg)
}
go func() {
wg.Wait() // &lt;-- wait for workers
close(ch) // &lt;-- causes main to break of range on ch.
}()
for n := range ch {
res = append(res, n)
}

huangapple
  • 本文由 发表于 2023年1月29日 12:09:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/75272546.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定