在切片通道中发送数据时发生死锁。

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

Deadlock while sending data to channel in slice of channels

问题

将数据发送到通道切片中的整数通道会导致死锁

代码的预期是创建5个(+1个fanInChan)通道。这些通道用于通过send()发送整数值,并在receive()中接收相同的值,最后将它们汇总到fanInChan中。

代码:-

package main

import (
	"fmt"
	"sync"
)

func main() {
	defer fmt.Println("About to exit!")
	fmt.Println("Started")

	channels := make([]chan int, 5)
	fanInChan := make(chan int)

	go send(channels)
	go recive(fanInChan, channels)

	for val := range fanInChan {
		fmt.Println("Fanin", val)
	}
}
func send(channels []chan int) {
	defer fmt.Println("Send Ended")
	fmt.Println("Send Started")

	for i := 0; i < 100; i++ {
		channels[i%5] <- i
	}

	for i := 0; i < 5; i++ {
		close(channels[i])
	}
}

func recive(fanin chan<- int, channels []chan int) {
	defer fmt.Println("Recive Ended")
	fmt.Println("Recive Started")

	var wg sync.WaitGroup
	wg.Add(5)

	for i := 0; i < 5; i++ {
		go func(inew int) {
			defer wg.Done()
			fmt.Println(inew)
			for v := range channels[inew] {
				fanin <- v
			}
		}(i)
	}

	wg.Wait()
	close(fanin)
}

Golang PlayGround

输出:-

Started
Send Started
Recive Started
4
1
2
3
0
fatal error: all goroutines are asleep - deadlock!
... //You can see rest on playground link above

问题是在send()函数的for循环中开始的

for i := 0; i < 100; i++ {
		channels[i%5] <- i
	}

英文:

Sending data to integer channel in slice of channels is resulting into deadlock

The code is expected to create 5 (+1 fanInChan) channels. These channels are used for send integer values through send() and receive the same in receive() and finally Fan-in the them to fanInChan.

Code:-

package main

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

func main() {
	defer fmt.Println(&quot;About to exit!&quot;)
	fmt.Println(&quot;Started&quot;)

	channels := make([]chan int, 5)
	fanInChan := make(chan int)

	go send(channels)
	go recive(fanInChan, channels)

	for val := range fanInChan {
		fmt.Println(&quot;Fanin&quot;, val)
	}
}
func send(channels []chan int) {
	defer fmt.Println(&quot;Send Ended&quot;)
	fmt.Println(&quot;Send Started&quot;)

	for i := 0; i &lt; 100; i++ {
		channels[i%5] &lt;- i
	}

	for i := 0; i &lt; 5; i++ {
		close(channels[i])
	}
}

func recive(fanin chan&lt;- int, channels []chan int) {
	defer fmt.Println(&quot;Recive Ended&quot;)
	fmt.Println(&quot;Recive Started&quot;)

	var wg sync.WaitGroup
	wg.Add(5)

	for i := 0; i &lt; 5; i++ {
		go func(inew int) {
			defer wg.Done()
			fmt.Println(inew)
			for v := range channels[inew] {
				fanin &lt;- v
			}
		}(i)
	}

	wg.Wait()
	close(fanin)
}

Golang PlayGround

OutPut:-

Started
Send Started
Recive Started
4
1
2
3
0
fatal error: all goroutines are asleep - deadlock!
... //You can see rest on playground link above

Problem is starting in a for loop inside send()

for i := 0; i &lt; 100; i++ {
channels[i%5] &lt;- i
}

答案1

得分: 3

语句channels := make([]chan int, 5)正在分配一个包含空通道的数组,该数组具有以下特性:

  • 阻塞从通道接收<- channel的操作
  • 阻塞将值发送到通道channel <- value的操作
  • 在关闭通道close(channel)时引发恐慌

因此,在接收整数值之前,您必须单独初始化每个通道。

在使用这些通道之前,您应该在channels数组中初始化这些通道。

for i := range channels {
    channels[i] = make(chan int)
}

将此代码插入到go send(channels)之前的行,并运行。

英文:

The statement channels := make([]chan int, 5) is allocating a array with nil channels which

  • Blocks receiving &lt;- channel from channel
  • Blocks sending channel &lt;- value into channel
  • panics on closing close(channel)

So you have to initialize each channel individually to recive integer values.

You should init the channels in the channels array before using those.

    for i := range channels {
channels[i] = make(chan int)
}

Insert this just before the line go send(channels) and run.

huangapple
  • 本文由 发表于 2021年5月21日 19:51:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/67636305.html
匿名

发表评论

匿名网友

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

确定