2

環境: OS X 10.8、Go 1.0.2

buffer-size 2 でチャネルを作成し、チャネルを 3 回書き込むと、エラーがスローされます。

throw: すべてのゴルーチンがスリープ状態 - デッドロック!

もちろん、それは正しいです。

しかし、ゴルーチンで channel を 4 回以上書き込むと、正常に動作します。なぜですか? チャネルの容量は 2 ですが、ゴルーチンがそれを無視したり、容量の設定を忘れたりするのはなぜですか? read-channel コードにコメントを付けて、誰もチャネルを読み取って容量を節約しないようにします。また、time.Sleep を使用して、すべてのゴルーチンが作業を完了するのを待ちます。

次のコードを確認してください: パッケージ メイン

//import "fmt"

func main() {
    c := make(chan int, 2)
    /*c <- 1
    c <- 2
    c <- 3*/
    for i:=0; i<4; i++ {
        go func(i int) {
            c <- i
            c <- 9
            c <- 9
            c <- 9
        }(i)
    }
    time.Sleep(2000 * time.Millisecond)

    /*for i:=0; i<4*2; i++ {
        fmt.Println(<-c)
    }*/
}

誰かヒットさせてくれませんか?みんなありがとう。

4

2 に答える 2

8

チャネルがバッファリングされている場合、これはバッファがいっぱいになるまでブロックされないことを意味します。バッファがいっぱいになると、送信ゴルーチンはチャネルに何かを追加しようとしてブロックされます。

これは、これがブロックされることを意味します:

c := make(chan int)
c <- 1          // Block here, this is unbuffered !
println(<-c)

そして、これブロックします:

c := make(chan int, 2)
c <- 1
c <- 2
c <- 3           // Block here, buffer is full !
println(<-c)

しかし、ゴルーチンとチャネルのポイントは、正確に物事を同時に実行することなので、これは機能します:

c := make(chan int)
go func() { c <- 1; }() // This will block in the spawned goroutine until...
println(<-c)            // ... this line is reached in the main goroutine

同様に:

c := make(chan int, 2)
go func() {  // `go ...` spawns a goroutine
    c <- 1   // Buffer is not full, no block
    c <- 2   // Buffer is not full, no block
    c <- 3   // Buffer is full, spawned goroutine is blocking until...
}()
println(<-c) // ... this line is reached in the main goroutine

あなたの例では、4 つの異なるゴルーチンを生成し、それらはすべて同じバッファリングされたチャネルに 4 つの数値を書き込みます。バッファが 2 < 16 であるため、最終的にブロックされます。

しかし問題の要点は、Go ポリシーがメインの goroutine だけを待つということです:

プログラムの実行は、メイン パッケージを初期化し、関数 main を呼び出すことによって開始されます。関数 main が戻ると、プログラムは終了します。他の (メインではない) ゴルーチンが完了するのを待ちません。

これは、最初の例では、メインのゴルーチンが line に到達したときにブロックしていたことを意味しますc <- 3。他のゴルーチンはブロックを解除する可能性のあることを実行できなかったため、ランタイムはプログラムがデッドロックしていることを検出し、エラーを報告しました。

ただし、2番目の例では、生成されたゴルーチンがブロックされますが、メインは実行の最後に到達するまで静かに続行します。その時点で、(ブロックされた) 生成されたすべてのゴルーチンは静かに強制終了され、エラーは報告されません。

于 2013-11-07T11:26:51.290 に答える