2016-12-06 4 views
0

golang docで説明したように、同期は低レベルライブラリルーチンのためのものです。golangを使用する適切な方法sync.WaitGroup

OnceおよびWaitGroupタイプ以外のほとんどは、 低レベルライブラリルーチンでの使用を想定しています。より高いレベルの同期は、チャネルと通信を介して行われたほうがよい( )。

私はこの声明をよく理解していないので、以下の例のように同期を使用します。
私の目的は、メインスレッドが他のすべてのスレッドが終了するまで待機させることです。これは、C++スレッドライブラリの.join()に似ています。

質問:
1:このような同期を使用するのは適切ですか?または、同期の代わりにチャンネルを使用する必要がありますか?
2:チャネルと同期の違いは何ですか?

var wg sync.WaitGroup  // declare the variable globally 

func send(a string, b string){ 
    defer wg.Done() 
    // do something 
} 
func main(){ 
    for i:=0; i<50; i++ { 
     wg.Add(1)    // add delta 
     go send("1111", "2222") 
    } 
    wg.Wait()     // wait until wg becomes 0 
} 

いずれかの提案がありがとうございます!ありがとう!

+1

私はあなたが求めているのかわからないんだけど、あなたは 'send'ゴルーチンが' 'main()の中のものと異なる' sync.WaitGroup'を持っているので、起こって何の同期はありません。 – JimB

+0

@JimBねえ、あいまいな声明には申し訳ありません!私は更新しました。実際には、ここでsyncを使って、C++スレッドで '.join()'のようなことをしています。ドキュメントからは、この方法でチャネルを実行することもできます。それは同期を使用するのが適切ですか? – Eagle

+1

はい、それはWaitGroupのためのものです。ゴルーチンのグループを待っている。それはパッケージ全体であり、必要なときに提供するものを使用するため、「同期を使用する正しい方法」の問題は理解できません。これは 'sync.WaitGroup'を使う正しい方法ではありません。なぜなら、' main'の 'wg'値は' send'の 'wg'値とは異なるからです。 – JimB

答えて

0

この例ではあなたに

var wg sync.WaitGroup 
done := make(chan bool) 

for _, element := range slice { 
    wg.Add(1) 
    go func(elem interface{}) { 
     wg.Done() 
    }(element) 
} 

go func() { 
    wg.Wait() 
    done <- true 
}() 

for { 
    select { 
    case done: 
     fmt.Println("All goroutines completed") 
     close(done) 
     return 
    case time.After(time.Minute * 2): 
     fmt.Println("Timeout!") 
     return 
    } 
} 
0

を助けることができる私はそれが適切であるかどうかわかりませんが、以下のコードでは、低いレベル「同期」を使用せずにトリックを行います。

package main 

func send(a string, b string, c chan bool) { 
// println(a, b) 
    c <- true; 
} 

func 
main() { 

    c := make(chan bool) 

    for i:=0; i<50; i++ { 
     go send("1111", "2222", c) 
    } 

    w := 0 
    for _ = range c { 
     w += 1 
     if w == 50 { break } 
    } 

} 
関連する問題