英文:
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 (
"fmt"
)
// Add adds the numbers in a and sends the result on 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)
}
答案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 < 2 {
s := <-ch
sum = sum + s
count++ // Increment the count after a routine sends its value
}
fmt.Println(sum)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论