1

我正在尝试编写一个简单的 Go 脚本来计算高达 8 的自然数之和:

package main
import "fmt" 

func sum(nums []int, c chan int) {
    var sum int = 0
    for _, v := range nums {
        sum += v    
    }
    c <- sum
}

func main() {
    allNums := []int{1, 2, 3, 4, 5, 6, 7, 8}
    c1 := make(chan int)
    c2 := make(chan int)
    sum(allNums[:len(allNums)/2], c1)
    sum(allNums[len(allNums)/2:], c2)
    a := <- c1
    b := <- c2
    fmt.Printf("%d + %d is %d :D", a, b, a + b)
}

但是,运行此程序会产生以下输出。

throw: all goroutines are asleep - deadlock!

goroutine 1 [chan send]:
main.sum(0x44213af00, 0x800000004, 0x420fbaa0, 0x2f29f, 0x7aaa8, ...)
    main.go:9 +0x6e
main.main()
    main.go:16 +0xe6

goroutine 2 [syscall]:
created by runtime.main
    /usr/local/go/src/pkg/runtime/proc.c:221

exit status 2

为什么我的代码会死锁?我很困惑,因为我使用 2 个单独的通道来计算小数。这两个渠道是如何依赖的?

4

3 回答 3

6

您的通道是无缓冲的,因此输入的c <- sum行将sum()阻塞,直到其他例程从另一端读取。

一种选择是将缓冲区添加到通道,因此您可以将值写入通道而不会阻塞:

c1 := make(chan int, 1)
c2 := make(chan int, 1)

或者,如果您将sum()函数作为单独的 goroutine 运行,那么它可能会在您的main()函数继续到它从通道读取的点时阻塞。

于 2012-12-27T08:55:42.000 回答
5

是的,你需要添加go喜欢

go sum(allNums[:len(allNums)/2], c1)

go sum(allNums[len(allNums)/2:], c2)

或者

c1 := make(chan int,1)
c2 := make(chan int,1)

添加频道缓存。

于 2012-12-27T08:50:29.687 回答
2

我有一段时间没有使用 Go,所以可能不是这样,但据我记得你需要go启动另一个 goroutine,所以:

go sum(allNums[:len(allNums)/2], c1)
go sum(allNums[len(allNums)/2:], c2)

如果sum没有在另一个 goroutine 上运行,它会尝试执行:

c <- sum

但是什么也没读cc尚未达到代码读取,因为它正在等待sum完成,并且sum不会完成,因为它需要先将其交给该代码!

于 2012-12-27T06:57:25.373 回答