質問

環境:OS X 10.8、GO 1.0.2

バッファサイズ2でチャンネルを作成します。チャンネルを3回記述すると、エラーが発生します。

スロー:すべてのゴルチンは眠っています - デッドロック!

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

しかし ゴルチンでチャンネルを4回以上書くと、それは正常に機能します、なぜですか?チャンネルの容量は2です。なぜゴルチンはそれを無視したり、容量設定を忘れたりするのですか?読み取りチャネルコードにコメントするので、誰もチャンネルを読んで容量を保存しません。また、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)
    }*/
}

誰かがいくつかのヒットを与えてくれませんか?みんなありがとう。

役に立ちましたか?

解決

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

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

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ポリシーが メインゴルウチンだけを待ちます:

プログラムの実行は、メインパッケージを初期化し、関数メインを呼び出すことから始まります。関数メインが戻ると、プログラムは終了します。他の(非メインの)ゴルウチンが完了するのを待つことはありません。

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

ただし、2番目の例では、 生み出した ゴルチンはブロックされますが、メインは実行の終了に達するまで静かに続きます。

他のヒント

ヴァル 良い答えを与えました。便利だと感じた追加のヒントを追加したいと思います。

ゴルチンを使用することを学ぶときは、ゼロバッファーチャネルを使用して最初に使用します。このようにして、間違いを犯すと、すぐにデッドロックが得られ、それを学ぶことができます。デッドロックしないコードを作成する方法を学ぶ必要があります。つまり、クライアントサーバーの関係に周期的な依存関係がないなどのトリックを学習することを意味します(ゴルチンがクライアントまたはサーバーとして書かれていると仮定します)。

バッファリングなしでネットワークについての理由は簡単ですが、これは最初は明らかではないかもしれません。

バッファリングは本当に便利ですが、パフォーマンスを向上させる手段と見なす必要があります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top