2017-01-19 1 views
2

私は特定の条件を待つことを試みています。これがどのように最もうまくいったかについてアドバイスをしたいと思います。私はview変数に読み込まれたファイルを、更新しています、ゴルーチンでチャンネルまたはsync.Condを使用して条件を待つ

type view struct { 
    timeFrameReached bool 
    Rows []*sitRow 
} 

:私はこの(簡体字)のように見える構造体を持っています。行数が増加し、timeFrameReachedは最終的にtrueになります。

他の場所で、私は本当のことを、以下の条件を待ちたい:

view.timeFrameReached == true || len(view.Rows) >= numRows 

私はチャンネルを習得しようとしていますし、Goの条件変数がどのように働くか、と私は最善の解決策はここにあるものを知っていただきたいと思います。理論的には、私はこれのような簡単なことをすることができます:

しかし、それは明らかにナイーブな解決策です。 numRowsという値はHTTPリクエストから来るので、条件メソッドは難しいようです。ゴルーチンは、条件をブロードキャストするタイミングを知らないため、探している行の数が分からないためです。

答えて

3

私はこれを条件変数で行うと思います。ウェイターがチェックしたい条件が真であるときに、それが真実であるとき(すなわち、チェックされているものが変更されたとき)にのみSignalが実行されるべきではないという概念ではない。

これを行うための通常のパターンは次のとおりです。次に

mutex.Lock() 
for { 
    view = getView() 
    if view.timeFrameReached == true || len(view.Rows) >= numRows { 
     break 
    } 
    cond.Wait(&mutex) 
} 
// Do stuff with view 
mutex.Unlock() 

、コードにviewが変更された場合:明らか

mutex.Lock() 
// Change view 
cond.Signal() // or cond.Broadcast() 
mutex.Unlock() 

、私はあなたのプログラムがどのように機能するかを知らなくても、これを書いています、あなたはいくつかの変更を加えなければならないかもしれません。

あなたは、信号を送るためにチャンネルを送信し、待つためにチャンネルから受信しようとすることで、何か似たようなことをすることができますが、それはもっと複雑です。また、複数のゴルーチンが待ち受けている場合は、cond.Broadcastを使って起床するようにすべての信号を送ることができます。

+0

これは良い考えです。私はまた思いついた別のアイデアを投稿しました。 – Josephus

+0

これは実行可能な解決策ですが、ミューテックスを使用すると結果的にスケーラビリティが得られないという経験から、カプセル化が困難な詳細なグローバルな知識が必要な場合があります。グルーオンとチャンネルは複合要素を形成します(これはCSPの中核的機能です)。これは、このような場合に代わりに使用しようとする理由です。 –

1

私はチャネルを介して必要な数の行と建物のゴルーチンビューは、メインスレッドが特定の数の行を要求しているかどうかを確認するために非ブロック受信を行います。そうであれば、条件が満たされたことを示すメッセージを返します。行の特定の数が必要な場合ここ

if numRows > len(viewFile.View.Rows) && !viewFile.View.TimeFrameReached { 
    // Send the required number of rows 
    rows <- numRows 
    // Wait for the prefetch loop to signal that the view file is ready 
    <-rows // Discard the response value and move on 
    view = getView() 
} 

ゴルーチンチェック:ここ

main関数は、行の数を要求します。そうであれば、準備完了時に肯定的な信号で応答する。その信号の値は重要ではありません。

select { 
    case numRows := <-rows: 
     if len(viewFile.View.Rows) >= numRows || viewFile.View.TimeFrameReached { 
      rows <- 1 
     } 
    default: 
} 
+0

これには2つの異なるチャンネルが必要です。そうでなければ、どのコードが 'numRows'を読むのか分かりません。 –

+0

任意のゴルーチン内で同じチャンネルの両端を使用するように注意してください。その場合、バッファされていないチャネルは通常、デッドロックにつながります。上の最初のコードスニペットにはこの問題があります。私は上記のAndyのコメントに同意します。 –

+0

代わりに、1つのチャネルを2回使用することもできます(上記と同じですが、2番目のインスタンスではsendの方向を変更します)。バッファされていないチャンネルの場合は、いずれかの方法で同期をとることができます。 –

関連する問題