英文:
Concurrency in nested for loop
问题
我正在尝试进行一些图像分析,并在每个 Goroutine 中分析每个像素。我的代码目前如下所示:
func FindEdgesV2(img image.Image) PointSet {
res := make(PointSet)
c := make(chan Point)
bounds := img.Bounds()
width, height := bounds.Max.X, bounds.Max.Y
size := width*height - width*2 - height*2 + 4
px := 0
bar := CreateBar(size, "reading pixels...")
for y := 1; y < height-1; y++ {
for x := 1; x < width-1; x++ {
go func(x, y int, c chan Point) {
gradient := [3][3]int{}
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
gradient[i][j] = int(Luminance(img.At(x-1+i, y-1+i)))
}
}
gx, gy := 0, 0
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
gx += gradient[i][j] * horizontal[i][j]
gy += gradient[i][j] * vertical[i][j]
}
}
colorCode := int(math.Sqrt(float64(gx*gx + gy*gy)))
if colorCode > 80 {
c <- Point{x, y}
}
}(x, y, c)
px++
bar.Set(px)
}
}
for p := range c {
res[p] = true
}
return res
}
然而,我一直遇到这个错误:
fatal error: all goroutines are asleep - deadlock!
我只是尝试使用多个 Goroutine 向通道写入数据,然后将该通道的内容放入一个映射中。我做错了什么?
英文:
I'm trying to do some image analysis, and am analyzing each pixel in a Goroutine. My code currently looks like this:
func FindEdgesV2(img image.Image) PointSet {
res := make(PointSet)
c := make(chan Point)
bounds := img.Bounds()
width, height := bounds.Max.X, bounds.Max.Y
size := width*height - width*2 - height*2 + 4
px := 0
bar := CreateBar(size, "reading pixels...")
for y := 1; y < height-1; y++ {
for x := 1; x < width-1; x++ {
go func(x, y int, c chan Point) {
gradient := [3][3]int{}
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
gradient[i][j] = int(Luminance(img.At(x-1+i, y-1+i)))
}
}
gx, gy := 0, 0
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
gx += gradient[i][j] * horizontal[i][j]
gy += gradient[i][j] * vertical[i][j]
}
}
colorCode := int(math.Sqrt(float64(gx*gx + gy*gy)))
if colorCode > 80 {
c <- Point{x, y}
}
}(x, y, c)
px++
bar.Set(px)
}
}
for p := range c {
res[p] = true
}
return res
}
However, I keep getting this error:
fatal error: all goroutines are asleep - deadlock!
I'm simply trying to write to a channel using multiple Goroutines, and then put the contents of that channel into a map. What am I doing wrong?
答案1
得分: 2
当所有的goroutine都完成时,你应该关闭通道。为了做到这一点,你首先需要使用WaitGroup来检测所有的goroutine是否都完成:
...
bar := CreateBar(size, "reading pixels...")
wg := sync.WaitGroup{}
for y := 1; y < height-1; y++ {
for x := 1; x < width-1; x++ {
wg.Add(1)
go func(x, y int, c chan Point) {
defer wg.Done()
...
然后在所有的goroutine都完成时关闭通道:
go func() {
wg.Wait()
close(c)
}()
for p := range c {
res[p] = true
}
英文:
You should close the channel when all goroutines are done. To do that, you first have to detect when all goroutines are done using a WaitGroup:
...
bar := CreateBar(size, "reading pixels...")
wg:=sync.WaitGroup{}
for y := 1; y < height-1; y++ {
for x := 1; x < width-1; x++ {
wg.Add(1)
go func(x, y int, c chan Point) {
defer wg.Done()
...
Then close the channel when all gorotines are done:
go func() {
wg.Wait()
close(c)
}()
for p := range c {
res = true
}
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论