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

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

golang deadlock error with waitgroups but no channels

问题

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

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

这是乘法函数的代码:

  1. func (M Matrix) Multiply(N Matrix) Matrix {
  2. var ans = BuildZeroMatrix(len(M), len(N[0]))
  3. var wg sync.WaitGroup
  4. wg.Add(len(M) * len(N[0]) * len(N))
  5. for i := 0; i < len(M); i++ {
  6. for j := 0; j < len(N[0]); j++ {
  7. for k := 0; k < len(N); k++ {
  8. wg.Add(1)
  9. go func(j int, i int, k int) {
  10. ans[i][j] += M[i][k] * N[k][j]
  11. defer wg.Done()
  12. }(j, i, k)
  13. }
  14. }
  15. }
  16. go func() {
  17. wg.Wait()
  18. }()
  19. return ans
  20. }

这是乘法函数。

  1. type Matrix [][]float64

这是Matrix类型。

  1. func BuildZeroMatrix(Row int, Col int) Matrix {
  2. var temp [][]float64
  3. for i := 0; i < Row; i++ {
  4. var tmp []float64
  5. for j := 0; j < Col; j++ {
  6. tmp = append(tmp, 0)
  7. }
  8. temp = append(temp, tmp)
  9. }
  10. M, _ := BuildMatrix(Row, Col, temp)
  11. return M
  12. }

这是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.

  1. func (M Matrix) Multiply(N Matrix) Matrix {
  2. var ans = BuildZeroMatrix(len(M), len(N[0]))
  3. var wg sync.WaitGroup
  4. wg.Add(len(M)*len(N[0])*len(N))
  5. for i := 0; i &lt; len(M); i++ {
  6. for j := 0; j &lt; len(N[0]); j++ {
  7. for k := 0; k &lt; len(N); k++ {
  8. wg.Add(1)
  9. go func(j int, i int, k int) {
  10. ans[i][j] += M[i][k] * N[k][j]
  11. defer wg.Done()
  12. }(j, i, k)
  13. }
  14. }
  15. }
  16. go func(){
  17. wg.Wait()
  18. }()
  19. return ans
  20. }

this is the multiply function.

  1. type Matrix [][]float64

this is Matrix.

  1. func BuildZeroMatrix(Row int, Col int) Matrix {
  2. var temp [][]float64
  3. for i := 0; i &lt; Row; i++ {
  4. var tmp []float64
  5. for j := 0; j &lt; Col; j++ {
  6. tmp = append(tmp, 0)
  7. }
  8. temp = append(temp, tmp)
  9. }
  10. M, _ := BuildMatrix(Row, Col, temp)
  11. return M
  12. }

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

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

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

更新: 请检查示例代码

  1. package main
  2. import (
  3. "fmt"
  4. "sync"
  5. )
  6. type Matrix [][]float64
  7. func (M Matrix) Multiply(N Matrix) Matrix {
  8. var ans = BuildZeroMatrix(len(M), len(N[0]))
  9. var wg sync.WaitGroup
  10. var mx sync.Mutex
  11. for i := 0; i < len(M); i++ {
  12. for j := 0; j < len(N[0]); j++ {
  13. for k := 0; k < len(N); k++ {
  14. wg.Add(1)
  15. go func(j int, i int, k int) {
  16. defer wg.Done()
  17. mx.Lock()
  18. ans[i][j] += M[i][k] * N[k][j]
  19. mx.Unlock()
  20. }(j, i, k)
  21. }
  22. }
  23. }
  24. wg.Wait()
  25. return ans
  26. }
  27. func BuildZeroMatrix(Row int, Col int) Matrix {
  28. var temp [][]float64
  29. for i := 0; i < Row; i++ {
  30. var tmp []float64
  31. for j := 0; j < Col; j++ {
  32. tmp = append(tmp, 0)
  33. }
  34. temp = append(temp, tmp)
  35. }
  36. return temp
  37. }
  38. func main() {
  39. var m, n Matrix
  40. // T1:
  41. m = Matrix{[]float64{1, 1, 1}, []float64{1, 1, 1}, []float64{1, 1, 1}}
  42. n = Matrix{[]float64{1, 1, 1}, []float64{1, 1, 1}, []float64{1, 1, 1}}
  43. fmt.Printf("%v", m.Multiply(n))
  44. // T2:
  45. m = Matrix{[]float64{1, 1, 1}, []float64{1, 1, 1}, []float64{1, 1, 1}}
  46. n = Matrix{[]float64{1, 1}, []float64{1, 1}, []float64{1, 1}}
  47. fmt.Printf("\n%v", m.Multiply(n))
  48. }
英文:

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

  1. func (M Matrix) Multiply(N Matrix) Matrix {
  2. var ans = BuildZeroMatrix(len(M), len(N[0]))
  3. var wg sync.WaitGroup
  4. wg.Add(len(M)*len(N[0])*len(N)) // This is unnecessary. You are already adding the goroutine inside the k loop.
  5. for i := 0; i &lt; len(M); i++ {
  6. for j := 0; j &lt; len(N[0]); j++ {
  7. for k := 0; k &lt; len(N); k++ {
  8. wg.Add(1)
  9. go func(j int, i int, k int) {
  10. 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.
  11. defer wg.Done()
  12. }(j, i, k)
  13. }
  14. }
  15. }
  16. go func(){
  17. 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.
  18. }()
  19. return ans
  20. }

UPDATED: Pls check the sample code

  1. package main
  2. import (
  3. &quot;fmt&quot;
  4. &quot;sync&quot;
  5. )
  6. type Matrix [][]float64
  7. func (M Matrix) Multiply(N Matrix) Matrix {
  8. var ans = BuildZeroMatrix(len(M), len(N[0]))
  9. var wg sync.WaitGroup
  10. var mx sync.Mutex
  11. for i := 0; i &lt; len(M); i++ {
  12. for j := 0; j &lt; len(N[0]); j++ {
  13. for k := 0; k &lt; len(N); k++ {
  14. wg.Add(1)
  15. go func(j int, i int, k int) {
  16. defer wg.Done()
  17. mx.Lock()
  18. ans[i][j] += M[i][k] * N[k][j]
  19. mx.Unlock()
  20. }(j, i, k)
  21. }
  22. }
  23. }
  24. wg.Wait()
  25. return ans
  26. }
  27. func BuildZeroMatrix(Row int, Col int) Matrix {
  28. var temp [][]float64
  29. for i := 0; i &lt; Row; i++ {
  30. var tmp []float64
  31. for j := 0; j &lt; Col; j++ {
  32. tmp = append(tmp, 0)
  33. }
  34. temp = append(temp, tmp)
  35. }
  36. return temp
  37. }
  38. func main() {
  39. var m, n Matrix
  40. // T1:
  41. m = Matrix{[]float64{1, 1, 1}, []float64{1, 1, 1}, []float64{1, 1, 1}}
  42. n = Matrix{[]float64{1, 1, 1}, []float64{1, 1, 1}, []float64{1, 1, 1}}
  43. fmt.Printf(&quot;%v&quot;, m.Multiply(n))
  44. // T2:
  45. m = Matrix{[]float64{1, 1, 1}, []float64{1, 1, 1}, []float64{1, 1, 1}}
  46. n = Matrix{[]float64{1, 1}, []float64{1, 1}, []float64{1, 1}}
  47. fmt.Printf(&quot;\n%v&quot;, m.Multiply(n))
  48. }

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:

确定