2011-07-29 8 views
4

while(true)ループにスレッドを入れて、条件が治療を開始しても問題ないかどうかテストするのは悪い習慣ですか?while(true)とwait + conditionの同期

void run() 
{ 
    for(;;) 
    { 
     if(dataReady) 
     { 
      processData(); 
     } 
    } 
} 

は/条件のメカニズムを待って使用することが好ましい。

私は待つことはほとんどないことを期待:

void run() 
{ 
    for(;;) 
    { 
     if(dataReady) 
     { 
      processData(); 
     } 
     lock_guard lock(mutex); 
     condition_.wait(lock); 
    } 
} 

もちろんの別のスレッドがcondition_.notify_one()

EDITを呼び出します。

+1

'dataReady'が何らかのアトミックまたはロック保護されたデータ型でない限り、データレースとなることに注意してください。 (例えば、それがバニラのブールだった場合) – GManNickG

+0

「私はほとんど待たないと思う」それは少し誤解を招く可能性があります。あなたが10,000,000で一度だけ待つと仮定します。ほとんどの場合、私は4GHzのCPUを稼働させているときにはまだかなり待っています。 –

答えて

4

をそれはあなたが待っていることを期待していた時間の量に依存します。

非常に短い期間のためとして、それはコンテキストスイッチを伴わないためビジーウェイトが好ましいことができコンテキストスイッチのオーバーヘッドは、ビジー待機ループ全体を上回ることがあります。

7

真実は処理サイクルを食べるだけなので悪い方法です。
2番目のアプローチは、スレッドが何らかの作業を実行しなければならない場合にのみ暗示されます。

+4

スピンロックが適切な時がありますが、そのような場合に働いている人は、一般的にそうであるかどうか尋ねる必要はありません。 :) – GManNickG

+0

親密な関係がありますか? – Puppy

+0

@DeadMG:**親密**定義:発表する;宣言する。出版する;コミュニケーションをとること;知らせる。 –

0

いつも後者を行うことをお勧めします。 これはスレッド化または並行処理の基本的な質問です...

スレッドが1つしかなく、プロセッサが何をしていたとしても消費された古いプロセッサでは、これは一般的でした物事を待つイディオム。現在、プロセッサにはいくつかのスレッドがあります。また、条件を満たすのを待っている場合は、電力を消費しないようにインテリジェントになっています。

0

前者は、1つのコアで100%CPUを使用するため、通常はひどい考えです。何もしない。他のスレッド(おそらく設定されているもの)によって使用された可能性のあるリソースを食べるでしょう。dataready

2番目の例では、通知されるまでスレッドは保留状態になります。 「Tは、CPU時間を食べる。

+2

あなたが言っていることは、多くの場合に当てはまりますが、常にそうとは限りません。ほとんど待たなければシステムコールのオーバーヘッドはおそらく* more * cpu timeを使用するでしょう。さらに、CPU使用率が低いのではなく、スピンロックが100%CPUを使用しているにもかかわらず、良いアイデアである可能性があります。 – jcoder

+0

@JohnB:*通常は*と書いてあることに注意してください。また、違いが何であるかわからない誰かには答えていることに注意してください。*したがって、ポーリングが望ましい非常にまれなケースについては気にする必要はありません。はい、あなたは正しいですが、私は実際にこれを助けることを見ていません – jalf

+0

確かに、それはすべて公正なコメントです。 – jcoder

0

はい、あります。悪い習慣。ビジーループは、ロックやスレッドなどの洗練された構造が利用できない場所でのみ、合法的な設計選択です。

ソフトウェアがデバイス上で実行されている唯一のアプリケーション(組み込みプロジェクトの場合もある)であることを保証できる場合は、ビジーなループに陥る可能性があります。

しかし、一般的には避けてください。

2

コンパイラが実際に変数をメモリから読み込み、メモリから読み込みを最適化しないようにする必要がある場合は、はループ内でに変更できません。これを行うには、変数を「volatile」と宣言する必要があります。

しかし、それだけでは十分ではありません。あるスレッドの変数の変更が他のスレッドに見えるようにするには、メモリバリアの形式が必要です。また、ストアと読み取りはCPUとキャッシュによって並べ替えられません。これがx86上にある場合、おそらくそれなしで立ち去るでしょう。しかし、このようなことをしたいのであれば、InterlockedIncrementのようなコンパイラ組み込み関数(ウィンドウ上、または他のプラットフォーム上でも同様)を使用する方がはるかに優れています。

ほとんどの場合、マルチコア処理に適した詳細が得られるため、条件変数やライブラリからのスピンロック(本質的には実装しようとしているもの)を使用する方が良いです。

+0

'volatile'は実際の解決策にそこにいる必要はありません。 – GManNickG

関連する問題