如果发送太多的值,通道将不会接收任何值。

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

Channel not receiving any values if sending to many values

问题

如果我将totalValues传递给getResults()的值设为大于12,那么从通道resultCh中将不会读取任何值,并且会出现fatal error: all goroutines are asleep - deadlock!的错误:

  1. package main
  2. type result struct {
  3. index int
  4. count int
  5. }
  6. func getResults(indexCh chan int, resultCh chan result, totalValues int) {
  7. allFields := make([]int, totalValues)
  8. for i := range allFields {
  9. indexCh <- i
  10. println("发送值", i)
  11. }
  12. println("发送所有值")
  13. for i := 0; i < totalValues; i++ {
  14. value := <-resultCh
  15. println("接收结果", value.index)
  16. allFields[value.index] = value.count
  17. }
  18. println("处理完成")
  19. }
  20. func processValue(indexCh chan int, ch chan result) {
  21. for index := range indexCh {
  22. println("接收值", index)
  23. ch <- result{
  24. index: index,
  25. count: index * index,
  26. }
  27. println("发送结果", index)
  28. }
  29. }
  30. func main() {
  31. bufferDepth := 4
  32. indexCh := make(chan int, bufferDepth)
  33. resultCh := make(chan result, bufferDepth)
  34. for i := 0; i < 4; i++ {
  35. go processValue(indexCh, resultCh)
  36. }
  37. // 当totalValues > 12时,出现goroutine休眠的问题
  38. getResults(indexCh, resultCh, 12)
  39. }

上述代码通过使用函数processValue()启动四个goroutine来工作,这些goroutine从缓冲通道indexCh中读取值。整数0到totalValues被插入到indexCh中,由getResults()函数完成。processValue()函数处理该值,并将结果放入缓冲通道resultCh中,然后由getResults()函数读取。

只有当totalValues大于12时,我才会观察到这个问题。因为没有从resultCh中读取任何值,所以不会打印出"Received result..."。

如果我将bufferDepth增加到5,那么对于totalValues大于12且小于15的情况,程序将成功完成。

如果resultCh的缓冲区深度与totalValues匹配,程序也将成功完成。

英文:

If I pass more than 12 for totalValues to getResults(), no values are read from channel resultCh and I get fatal error: all goroutines are asleep - deadlock!:

  1. package main
  2. type result struct {
  3. index int
  4. count int
  5. }
  6. func getResults(indexCh chan int, resultCh chan result, totalValues int) {
  7. allFields := make([]int, totalValues)
  8. for i := range allFields {
  9. indexCh &lt;- i
  10. println(&quot;Sent value&quot;, i)
  11. }
  12. println(&quot;Sent all values&quot;)
  13. for i := 0; i &lt; totalValues; i++ {
  14. value := &lt;-resultCh
  15. println(&quot;Received result&quot;, value.index)
  16. allFields[value.index] = value.count
  17. }
  18. println(&quot;Done processing&quot;)
  19. }
  20. func processValue(indexCh chan int, ch chan result) {
  21. for index := range indexCh {
  22. println(&quot;Received value&quot;, index)
  23. ch &lt;- result{
  24. index: index,
  25. count: index * index,
  26. }
  27. println(&quot;Sent result&quot;, index)
  28. }
  29. }
  30. func main() {
  31. bufferDepth := 4
  32. indexCh := make(chan int, bufferDepth)
  33. resultCh := make(chan result, bufferDepth)
  34. for i := 0; i &lt; 4; i++ {
  35. go processValue(indexCh, resultCh)
  36. }
  37. // Value &gt; 12 results in goroutine asleep
  38. getResults(indexCh, resultCh, 12)
  39. }

The above code works by launching four goroutines using function processValue() that read values from buffered channel indexCh. Integers 0 to totalValues are inserted into indexCh by getResults(). processValue() processes the value and puts the result onto buffered channel resultCh, which is read by a getResults().

I only only observe this problem when totalValues is greater than 12. No values are read from resultCh because "Received result..." is not printed.

If I increase bufferDepth to five, the program completes successfully for totalValues > 12 and < 15.

The program also completes successfully if the buffer depth of resultCh matches totalValues.

答案1

得分: 2

getResults首先将所有的值写入通道。有4个goroutine在监听,所以每个goroutine都会接收这些值,并且它们在写入结果通道时被阻塞。通道的缓冲区大小为4。因此,在被阻塞之前,每个goroutine可以将4个值写入结果通道。

4个goroutine + 4个索引通道大小 + 4个结果通道大小 = 12个条目

之后,processValue在写入通道时被阻塞,因为getResults也在写入indexCh时被阻塞。

英文:

getResults starts by writing all values to the channel. There are 4 goroutines listening, so each picks up those values, and they are blocked writing to the result channel. Channels have buffer sizes of 4. So 4 goroutines each can write a total of 4 values to result channel before blocking.

4 goroutines + 4 index channel size + 4 result channel size = 12 entries

After that, the processValue is blocked at writing to the channel, because getResults are also blocked writing to the indexCh.

huangapple
  • 本文由 发表于 2022年8月18日 23:12:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/73405498.html
匿名

发表评论

匿名网友

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

确定