4

go をいじって、次のコードをまとめました。

package main

import "fmt"

const N = 10

func main() {
    ch := make(chan int, N)
    done := make(chan bool)

    for i := 0; i < N; i++ {
        go (func(n int, ch chan int, done chan bool) {
            for i := 0; i < N; i++ {
                ch <- n*N + i
            }
            done <- true
        })(i, ch, done)
    }

    numDone := 0
    for numDone < N {
        select {
        case i := <-ch:
            fmt.Println(i)
        case <-done:
            numDone++
        }
    }

    for {
        select {
        case i := <-ch:
            fmt.Println(i)
        default:
            return
        }
    }
}

基本的に、N 個のチャネルで何らかの作業を行い、同じチャネルで報告しています。すべてのチャネルがいつ完了したかを知りたいのです。したがってdone、各ワーカーゴルーチンがメッセージを送信するこの別のチャネルがあり (メッセージは重要ではありません)、これにより main はそのスレッドを完了としてカウントします。カウントが N になると、実際には完了です。

これは「いい」ですか?これを行うためのより慣用的な方法はありますか?

done編集:少し明確にするために、チャネルがチャネルの閉鎖が目的と思われる仕事をしているように見えるので、私は疑わしいですが、もちろん、すべてのルーチンが同じチャネルを共有するため、ゴルーチンで実際にチャネルを閉じることはできません. だから私はdone、ある種の「バッファリングされた閉鎖」を行うチャネルをシミュレートするために使用しています。

edit2: 元のコードは実際には機能していませんでした。doneこれは、ルーチンからのシグナルが、ちょうど置かれた int の前に読み取られることがあったためchです。「クリーンアップ」ループが必要です。

4

6 に答える 6

1

WaitGroup を使用するだけです。これらは組み込みのプリミティブであり、本質的にさまざまなゴルーチンの処理が完了するのを待つことができます。

http://golang.org/pkg/sync/#WaitGroup

疑問点としては、チャネルを閉じることによって行われること (永続的に行われる) と、作業が行われること (一時的に行われること) は異なるということです。

于 2013-04-15T17:07:44.813 に答える
1

最初の概算では、コードは多かれ少なかれ問題ないように思えます。

詳細を書くと、「ch」はバッファリングする必要があります。また、「完了」チャネルのゴルーチン「アカウンティング」は、sync.WaitGroup に置き換えられる可能性があります。

于 2013-04-15T17:15:30.403 に答える
0

私は自分のコードで同じ問題を扱っていましたが、これが十分な解決策であることがわかりました。

答えは、すべて単一のチャネルを介して送信する複数のゴルーチンを処理するための Go のイディオムを提供します。

于 2013-04-16T23:11:48.250 に答える