1

8 までの自然数の合計を計算する単純な Go スクリプトをプログラムしようとしています。

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 つの別々のチャネルを使用しているため、混乱しています。2 つのチャネルはどのように依存しているのでしょうか。

4

3 に答える 3

6

チャネルはバッファリングされていないため、他のルーチンが反対側から読み取るまで、c <- sumラインインはブロックされます。sum()

1 つのオプションは、チャネルにバッファを追加することです。これにより、チャネルをブロックせずにチャネルに値を書き込むことができます。

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

sum()あるいは、関数を別のゴルーチンとして実行すると、関数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から、別のゴルーチンを開始する必要があります。

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

sumが別のゴルーチンで実行されていない場合は、以下を実行しようとします。

c <- sum

しかし、何も読んでいませんc; 終了を待っているため、コードの読み取りcにはまだ到達していません。また、最初にそのコードにコードを渡す必要があるため、終了しません。sumsum

于 2012-12-27T06:57:25.373 に答える