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

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

Channel not receiving any values if sending to many values

问题

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

package main

type result struct {
	index int
	count int
}

func getResults(indexCh chan int, resultCh chan result, totalValues int) {
	allFields := make([]int, totalValues)

	for i := range allFields {
		indexCh <- i
		println("发送值", i)
	}

	println("发送所有值")

	for i := 0; i < totalValues; i++ {
		value := <-resultCh
		println("接收结果", value.index)

		allFields[value.index] = value.count
	}

	println("处理完成")
}

func processValue(indexCh chan int, ch chan result) {
	for index := range indexCh {
		println("接收值", index)

		ch <- result{
			index: index,
			count: index * index,
		}

		println("发送结果", index)
	}
}

func main() {
	bufferDepth := 4
	indexCh := make(chan int, bufferDepth)
	resultCh := make(chan result, bufferDepth)

	for i := 0; i < 4; i++ {
		go processValue(indexCh, resultCh)
	}

	// 当totalValues > 12时,出现goroutine休眠的问题
	getResults(indexCh, resultCh, 12)
}

上述代码通过使用函数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!:

package main

type result struct {
	index int
	count int
}

func getResults(indexCh chan int, resultCh chan result, totalValues int) {
	allFields := make([]int, totalValues)

	for i := range allFields {
		indexCh &lt;- i
		println(&quot;Sent value&quot;, i)
	}

	println(&quot;Sent all values&quot;)

	for i := 0; i &lt; totalValues; i++ {
		value := &lt;-resultCh
		println(&quot;Received result&quot;, value.index)

		allFields[value.index] = value.count
	}

	println(&quot;Done processing&quot;)
}

func processValue(indexCh chan int, ch chan result) {
	for index := range indexCh {
		println(&quot;Received value&quot;, index)

		ch &lt;- result{
			index: index,
			count: index * index,
		}

		println(&quot;Sent result&quot;, index)
	}
}

func main() {
	bufferDepth := 4
	indexCh := make(chan int, bufferDepth)
	resultCh := make(chan result, bufferDepth)

	for i := 0; i &lt; 4; i++ {
		go processValue(indexCh, resultCh)
	}

	// Value &gt; 12 results in goroutine asleep
	getResults(indexCh, resultCh, 12)
}

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:

确定