2016-09-29 4 views
2

私が同時に操作されている整数のスライス、持っている:私は同時に行くルーチンを実行しているの上限を持っているために、セマフォとしてバッファリングされたチャネルを使用していバッファされたチャネル(セマフォ)が空になるまで待つ方法はありますか?

ints := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} 

を:

sem := make(chan struct{}, 2) 

for _, i := range ints { 
    // acquire semaphore 
    sem <- struct{}{} 

    // start long running go routine 
    go func(id int, sem chan struct{}) { 
    // do something 

    // release semaphore 
    <- sem 
    }(i, sem) 
} 

上記のコードは、最後または最後の2つの整数に達するまでうまくいきます。なぜなら、プログラムは最後の実行ルーチンが終了する前に終了するからです。

質問:バッファされたチャネルがなくなるのを待つ方法を教えてください。

+0

よりcheeperです。バッファされたチャンネルは一杯になるとブロックしますが、空になるまでブロックする言語機能はありません。 – evanmcdonnal

答えて

8

このようにセマフォ(この場合はチャネル)を使用することはできません。値を処理してより多くのゴ​​ルーチンをディスパッチしている間は、それが空でないという保証はありません。これは特に仕事をディスパッチするので心配はありませんが、チャンネルの長さをチェックするレースフリーの方法はないので、チャンネルの長さが0になるのを待つプリミティブはありません。

sync.WaitGroupすべてのゴルーチンが完了するまで待つ

​​
+1

ありがとう、私はまた 'WaitGroup'を使うことを考えました。これは正しい方法のように感じる! – Kiril

0

あなたのゴールーチンが完了するのを待っている人はいません。したがって、プログラムは最後の2つのゴールルーチンが完了する前に終了します。ワークグループを使用して、プログラムが終了する前にすべてのゴールルーチンが完了するのを待つことができます。これはそれをより良く伝えます - https://nathanleclaire.com/blog/2014/02/15/how-to-wait-for-all-goroutines-to-finish-executing-before-continuing/

+0

ありがとう、私はそれを避ける方法を探していたし、 'WorkGroup'は完璧に動作します。 JimBの答えがこれを明らかにした – Kiril

2

データを処理するために "ワーカープール"を使用してください。あなたがミューテックスか何かを使用して得たように、その中の変数のためのメモリを割り当てると、 int型をゴルーチンを実行...

ints := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} 

ch := make(chan int) 

var wg sync.WaitGroup 

// run worker pool 
for i := 2; i > 0; i-- { 
    wg.Add(1) 

    go func() { 
     defer wg.Done() 

     for id := range ch { 
      // do something 
      fmt.Println(id) 
     } 
    }() 
} 

// send ints to workers 
for _, i := range ints { 
    ch <- i 
} 

close(ch) 

wg.Wait() 
関連する問題