2017-08-26 12 views
3
var condition bool 
var wg sync.WaitGroup 
for _, item := range items { 
    wg.Add(1) 
    go func(item) { 
     if meetsCondition(item) { 
      condition = true 
     } 
     wg.Done() 
    }(item) 
} 
wg.Wait() 
// is it safe to check condition here? 

この質問についてのディスカッションは、こちらの古いgoフォーラムで: https://groups.google.com/forum/#!topic/golang-nuts/5oHzhzXCcmM答えははい、安全です。その後、議論は原子などの使用を控えています。これは私が尋ねたいものではありません。この場合、WaitGroup.Wait()はメモリバリアを意味しますか?

仕様にWaitGroupという言葉が1つも書かれておらず、WaitGroup.Wait:WaitGroupカウンタがゼロになるまでWaitブロックと書かれています。 には、何らかの出来事の前に関係が設定されていませんか?

最初の答え「wg.Wait returns後の状態を確認することは安全です」が非公式であることを意味しますか?それが正式であれば、その理由は何ですか?あなたが答えるなら、ありがとう。

更新: これは@ peterSOの@ raviの回答の後に更新されています。ありがとう。

明らかに、アイテム数> 1を選択すると、競合状態が発生する可能性があります。ヒント:条件はtrueにのみ設定できます。それでも、私は同じ質問があります。

  1. 基礎となるアーキテクチャは
  2. 項目の
  3. 数は1

アップデート2 Iすることができる唯一のx86、x64のか、ARMにすることができます。

そしておそらく、私がいることを述べている必要があります項目数== 1の場合のフォローアップの質問を作成しました: Can you make this 'incorrectly synchronized' test fail?

答えて

0

wg.Wait()、しかしの後にチェックすることは絶対に安全です.に複数のgoルーチンによって同時に書き込まれることを避けるために、mutexを保護する必要があります。だから@peterSOは彼のコードで行番号20の競合状態b'cosを打つのです。condition = true複数のgoルーチンが同時にconditionを設定しようとしています。ここには、サンプル数https://play.golang.org/p/o3v6s_2qsYと20k go rountinesがあります。

ベストプラクティスとして、defer wg.Done()をgoルーチンの最初の部分に追加すると、その間にreturn文があっても、wg.Done()が呼び出されます。

1

はい。 wg.Wait()wg.Done()の間には何らかの関係があります。この単純な事実は、docまたはMM #7948に記載されていない何らかの理由によるものです。それを明確にしてくれたありがとうIan Lance Taylor golang-nuts/5oHzhzXCcmM競合状態については、同じスレッドでさらに読むことができます。

それは、自分自身を同時に呼び出す言語では、基本的なことを行うために「良い言葉」に依存しなければならないことに失望しています(右)。

関連する問題