在Go语言中的死锁问题,两个例程分割工作。

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

Deadlock in Go, two routines splitting work

问题

我在go语言中遇到了一个死锁问题。

这个程序接受一个整数数组a,并将其分成两部分。然后它在两个不同的例程中分别处理这两部分,并求和所有元素。之后,它应该将这两个结果发送到通道res中。然后,这两个res(现在是ch)应该相加并打印出来。

我的问题是:我尝试通过移动close函数来解决死锁问题,但似乎没有任何帮助。显然,只有一个例程Add运行时它能正常工作。

package main

import (
	"fmt"
)

// Add将a中的数字相加,并将结果发送到res通道中。
func Add(a []int, res chan<- int) {
	sum := 0
	for i := range a {
		sum = sum + a[i]
	}
	res <- sum
}

func main() {
	a := []int{1, 2, 3, 4, 5, 6, 7}

	n := len(a)
	ch := make(chan int)
	go Add(a[:n/2], ch)
	go Add(a[n/2:], ch)

	sum := 0
	for s := range ch {
		sum = sum + s
	}
	//close(ch)

	fmt.Println(sum)
}
英文:

I'm a bit stuck on a deadlock issue in go.

This program takes an array of ints, a, and splits it into two. Then it takes these two parts in two different routines and sum up all elements. After this, it's supposed to send the two results in the channel res. The two res (now ch) then should be added together and print.

My problem: I've tried to tackle the deadlock problem by moving about close-functions a lot, but nothing seems to help. It works well with only one routine Add running obviously.

package main

import (
	&quot;fmt&quot;
)

// Add adds the numbers in a and sends the result on res.
func Add(a []int, res chan&lt;- int) {
	sum := 0
	for i := range a {
		sum = sum + a[i]
	}
	res &lt;- sum
}

func main() {
	a := []int{1, 2, 3, 4, 5, 6, 7}

	n := len(a)
	ch := make(chan int)
	go Add(a[:n/2], ch)
	go Add(a[n/2:], ch)


	sum := 0
	for s := range ch {
		sum = sum + s
	}
	//close(ch)

	fmt.Println(sum)
}

答案1

得分: 4

你从未关闭通道,所以range没有信号可以退出。它将继续尝试接收,但没有剩余的发送者。

你可以通过某种方式让你的Add()函数在最后一个结束时看到它,以便它可以close()通道,或者你可以只减少一个计数器而不是在循环中使用range,这样你就不需要使用close()

func main() {
	a := []int{1, 2, 3, 4, 5, 6, 7}

	n := len(a)
	ch := make(chan int)
	go Add(a[:n/2], ch)
	go Add(a[n/2:], ch)

	sum := 0

    // 计算通道上发送的消息数量
	count := 0

    // 在计数小于总协程数的情况下运行循环
	for count < 2 {
		s := <-ch
		sum = sum + s
		count++  // 在协程发送其值后递增计数
	}
	fmt.Println(sum)
}

DEMO: http://play.golang.org/p/oHcrUStjmm

英文:

You're never closing the channel so there's no signal for the range to quit. It'll just keep on trying to receive, but there's nothing left that's sending.

You would either need to have some way for your Add() function to see when it ends if it is the last one so that it can close() the channel, or you could just decrement a counter instead of using range in the loop so that you don't need to use close().

func main() {
	a := []int{1, 2, 3, 4, 5, 6, 7}

	n := len(a)
	ch := make(chan int)
	go Add(a[:n/2], ch)
	go Add(a[n/2:], ch)

	sum := 0

    // counts the number of messages sent on the channel
	count := 0

    // run the loop while the count is less than the total number of routines
	for count &lt; 2 {
		s := &lt;-ch
		sum = sum + s
		count++  // Increment the count after a routine sends its value
	}
	fmt.Println(sum)
}

DEMO: http://play.golang.org/p/oHcrUStjmm

huangapple
  • 本文由 发表于 2013年3月20日 07:35:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/15512549.html
匿名

发表评论

匿名网友

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

确定