使用WaitGroup但没有使用通道的Golang死锁错误。

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

golang deadlock error with waitgroups but no channels

问题

我是你的中文翻译助手,以下是翻译好的内容:

我刚开始学习Go语言。我有一个关于矩阵及其运算的项目。我需要在我的乘法函数中使用goroutine(免责声明:这不是我的代码,这是一个小组项目,我需要在函数中添加goroutine)。
我在网上搜索了一些方法(我使用的方法),但是我遇到了一个致命错误:所有的goroutine都处于休眠状态,死锁!或者代码运行时间太长。

这是乘法函数的代码:

func (M Matrix) Multiply(N Matrix) Matrix {
	var ans = BuildZeroMatrix(len(M), len(N[0]))
	var wg sync.WaitGroup
	wg.Add(len(M) * len(N[0]) * len(N))
	for i := 0; i < len(M); i++ {
		for j := 0; j < len(N[0]); j++ {
			for k := 0; k < len(N); k++ {
				wg.Add(1)
				go func(j int, i int, k int) {
					ans[i][j] += M[i][k] * N[k][j]
					defer wg.Done()
				}(j, i, k)
			}
		}
	}
	go func() {
		wg.Wait()
	}()
	return ans
}

这是乘法函数。

type Matrix [][]float64

这是Matrix类型。

func BuildZeroMatrix(Row int, Col int) Matrix {
	var temp [][]float64
	for i := 0; i < Row; i++ {
		var tmp []float64
		for j := 0; j < Col; j++ {
			tmp = append(tmp, 0)
		}
		temp = append(temp, tmp)
	}
	M, _ := BuildMatrix(Row, Col, temp)
	return M
}

这是BuildZeroMatrix函数。
我给这个函数传入了两个500*500的矩阵,它需要大约10秒才能运行完毕,或者会出现致命错误。
我在解决这个问题的过程中找到的每篇帖子都涉及到通道(channel),但是我没有使用通道。

英文:

im new to go. i have this project it's about matrices and their operations. i am supposed to use goroutine in my multiply function.(also disclaimer:this is not my code, its a group project im supposed to add the goroutine to the function)
i've searched around and seen this way(the way that i used) in different sites.however i get a fatal error: all the goroutines are asleep.deadlock!
or it just takes way too long for the code to run.


    func (M Matrix) Multiply(N Matrix) Matrix {
    	var ans  = BuildZeroMatrix(len(M), len(N[0]))
    	var wg sync.WaitGroup
    	wg.Add(len(M)*len(N[0])*len(N))
    	for i := 0; i &lt; len(M); i++ {
    		for j := 0; j &lt; len(N[0]); j++ {
    			for k := 0; k &lt; len(N); k++ {
    				wg.Add(1)
    				go func(j int, i int, k int) {
    					ans[i][j] += M[i][k] * N[k][j]
    					defer wg.Done()
    				}(j, i, k)
    			}
    		}
    	}
    	go func(){
    		wg.Wait()

    	}()
    	return ans
    }

this is the multiply function.

type Matrix [][]float64

this is Matrix.


    func BuildZeroMatrix(Row int, Col int) Matrix {
    	var temp [][]float64
    	for i := 0; i &lt; Row; i++ {
    		var tmp []float64
    		for j := 0; j &lt; Col; j++ {
    			tmp = append(tmp, 0)
    		}
    		temp = append(temp, tmp)
    	}
    	M, _ := BuildMatrix(Row, Col, temp)
    	return M
    }

and this is the buildzeromatrix function.
i give the function 2 500*500 matrices and it takes about 10 seconds to run or it gives the fatal error.
every post i found on this problem had channels in them and their problem was with the channel.however i dont have any.

答案1

得分: 2

只是指出这段代码中的错误。请检查内联注释。

func (M Matrix) Multiply(N Matrix) Matrix {
    var ans  = BuildZeroMatrix(len(M), len(N[0]))
    var wg sync.WaitGroup
    wg.Add(len(M)*len(N[0])*len(N)) // 这是不必要的。你已经在 k 循环内添加了 goroutine。
    for i := 0; i < len(M); i++ {
        for j := 0; j < len(N[0]); j++ {
            for k := 0; k < len(N); k++ {
                wg.Add(1)
                go func(j int, i int, k int) {
                    ans[i][j] += M[i][k] * N[k][j] // 这是数据竞争区域。多个 goroutine 将尝试写入同一地址。你需要在这里加锁。
                    defer wg.Done()
                }(j, i, k)
            }
        }
    }
    go func(){
        wg.Wait() // 不应该在 goroutine 内部等待 goroutine 完成。因为在这里你不等待这个 goroutine 完成。
    }()
    return ans
}

更新: 请检查示例代码

package main

import (
	"fmt"
	"sync"
)

type Matrix [][]float64

func (M Matrix) Multiply(N Matrix) Matrix {
	var ans = BuildZeroMatrix(len(M), len(N[0]))
	var wg sync.WaitGroup
	var mx sync.Mutex
	for i := 0; i < len(M); i++ {
		for j := 0; j < len(N[0]); j++ {
			for k := 0; k < len(N); k++ {
				wg.Add(1)
				go func(j int, i int, k int) {
					defer wg.Done()
					mx.Lock()
					ans[i][j] += M[i][k] * N[k][j]
					mx.Unlock()
				}(j, i, k)
			}
		}
	}
	wg.Wait()
	return ans
}
func BuildZeroMatrix(Row int, Col int) Matrix {
	var temp [][]float64
	for i := 0; i < Row; i++ {
		var tmp []float64
		for j := 0; j < Col; j++ {
			tmp = append(tmp, 0)
		}
		temp = append(temp, tmp)
	}
	return temp
}

func main() {
	var m, n Matrix

	// T1:
	m = Matrix{[]float64{1, 1, 1}, []float64{1, 1, 1}, []float64{1, 1, 1}}
	n = Matrix{[]float64{1, 1, 1}, []float64{1, 1, 1}, []float64{1, 1, 1}}
	fmt.Printf("%v", m.Multiply(n))

	// T2:
	m = Matrix{[]float64{1, 1, 1}, []float64{1, 1, 1}, []float64{1, 1, 1}}
	n = Matrix{[]float64{1, 1}, []float64{1, 1}, []float64{1, 1}}
	fmt.Printf("\n%v", m.Multiply(n))
}
英文:

Just pointing out the mistakes in this snippet. Please check the inline comments.

func (M Matrix) Multiply(N Matrix) Matrix {
    var ans  = BuildZeroMatrix(len(M), len(N[0]))
    var wg sync.WaitGroup
    wg.Add(len(M)*len(N[0])*len(N)) // This is unnecessary. You are already adding the goroutine inside the k loop.
    for i := 0; i &lt; len(M); i++ {
        for j := 0; j &lt; len(N[0]); j++ {
            for k := 0; k &lt; len(N); k++ {
                wg.Add(1)
                go func(j int, i int, k int) {
                    ans[i][j] += M[i][k] * N[k][j] // This is data race area. Multiple goroutines will try to write to the same address. You will need a lock here.
                    defer wg.Done()
                }(j, i, k)
            }
        }
    }
    go func(){
        wg.Wait() // Wait()ing for goroutines to be completed should not be done inside a goroutine. Because here you don&#39;t wait for this goroutine to be done.
    }()
    return ans
}

UPDATED: Pls check the sample code

package main

import (
	&quot;fmt&quot;
	&quot;sync&quot;
)

type Matrix [][]float64

func (M Matrix) Multiply(N Matrix) Matrix {
	var ans = BuildZeroMatrix(len(M), len(N[0]))
	var wg sync.WaitGroup
	var mx sync.Mutex
	for i := 0; i &lt; len(M); i++ {
		for j := 0; j &lt; len(N[0]); j++ {
			for k := 0; k &lt; len(N); k++ {
				wg.Add(1)
				go func(j int, i int, k int) {
					defer wg.Done()
					mx.Lock()
					ans[i][j] += M[i][k] * N[k][j]
					mx.Unlock()
				}(j, i, k)
			}
		}
	}
	wg.Wait()
	return ans
}
func BuildZeroMatrix(Row int, Col int) Matrix {
	var temp [][]float64
	for i := 0; i &lt; Row; i++ {
		var tmp []float64
		for j := 0; j &lt; Col; j++ {
			tmp = append(tmp, 0)
		}
		temp = append(temp, tmp)
	}
	return temp
}

func main() {
	var m, n Matrix

	// T1:
	m = Matrix{[]float64{1, 1, 1}, []float64{1, 1, 1}, []float64{1, 1, 1}}
	n = Matrix{[]float64{1, 1, 1}, []float64{1, 1, 1}, []float64{1, 1, 1}}
	fmt.Printf(&quot;%v&quot;, m.Multiply(n))

	// T2:
	m = Matrix{[]float64{1, 1, 1}, []float64{1, 1, 1}, []float64{1, 1, 1}}
	n = Matrix{[]float64{1, 1}, []float64{1, 1}, []float64{1, 1}}
	fmt.Printf(&quot;\n%v&quot;, m.Multiply(n))
}

huangapple
  • 本文由 发表于 2022年3月8日 17:20:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/71392611.html
匿名

发表评论

匿名网友

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

确定