2013-03-30 13 views
8

私はいくつかの計算を並行して実行しようとしています。このプログラムは、各ワーカーのゴルーチンが解決されたパズルの「ピース」を、作業者ルーチンから送られたすべてのものを受け取って組み立てるのを待つコントローラのゴルーチンに送り返すように設計されています。複数のゴルーチンが送信しているチャンネルを閉じるにはどうすればいいですか?

単一チャネルを閉じるためのidomatic Goとは何ですか?閉じたチャンネルを送信する可能性があるので、私は各ゴルーチンのチャンネルで閉じることはできません。同様に、どのゴルーチンが最初に終了するかを事前に決定する方法はありません。ここにsync.WaitGroupは必要ですか?

答えて

9

は、あなたが探しているものを行うにはsync.WaitGroupを使用した例である

この例では、整数の長ったらしいリストを受け入れ、そしてハンドリングNパラレル労働者によって入力の等しいサイズのチャンクをそれらすべてを合計しますデータ。それはgo playgroundで実行することができます:

package main 

import (
    "fmt" 
    "sync" 
) 

const WorkerCount = 10 

func main() { 
    // Some input data to operate on. 
    // Each worker gets an equal share to work on. 
    data := make([]int, WorkerCount*10) 

    for i := range data { 
     data[i] = i 
    } 

    // Sum all the entries. 
    result := sum(data) 

    fmt.Printf("Sum: %d\n", result) 
} 

// sum adds up the numbers in the given list, by having the operation delegated 
// to workers operating in parallel on sub-slices of the input data. 
func sum(data []int) int { 
    var sum int 

    result := make(chan int) 
    defer close(result) 

    // Accumulate results from workers. 
    go func() { 
     for { 
      select { 
      case value := <-result: 
       sum += value 
      } 
     } 
    }() 

    // The WaitGroup will track completion of all our workers. 
    wg := new(sync.WaitGroup) 
    wg.Add(WorkerCount) 

    // Divide the work up over the number of workers. 
    chunkSize := len(data)/WorkerCount 

    // Spawn workers. 
    for i := 0; i < WorkerCount; i++ { 
     go func(i int) { 
      offset := i * chunkSize 

      worker(result, data[offset:offset+chunkSize]) 
      wg.Done() 
     }(i) 
    } 

    // Wait for all workers to finish, before returning the result. 
    wg.Wait() 

    return sum 
} 

// worker sums up the numbers in the given list. 
func worker(result chan int, data []int) { 
    var sum int 

    for _, v := range data { 
     sum += v 
    } 

    result <- sum 
} 
+0

ありがとう、これは私が必要としていたために完璧に働いています。 –

+0

そのコードのいくつかは少し奇妙です。特に、for/single-caseを選択したgoroutineは結果を蓄積し、同期なしで変数を上書きします。いくつかのマイナーな再編成やものがより信頼できる/理解しやすくなる:http://play.golang.org/p/5bmlTbdIQa – Dustin

4

はい、これはsync.WaitGroupの完璧な使用例です。

もう1つの方法として、ゴルーチンごとに1つのチャンネルと、各チャンネルから1つのチャンネルにフィードする1つのマルチプレクサのゴルーチンを使用することができます。しかし、それは扱いにくいので、私はちょうどsync.WaitGroupに行くだろう。ここで

関連する問題