2011-12-07 13 views
4

私は、非同期タイマーを作成するためにブーストライブラリを使用しているクロスプラットフォームのC++プログラムを使用しています。2つのスレッドが同じbool変数に同時にアクセスするとどうなりますか?

bool receivedInput = false; 

1つのスレッドが他のスレッドがコールバックが10秒ごとに呼び出されるタイマーを実行するために待機し、入力

string argStr; 
while (1) 
{ 
    getline(cin, argStr); 
    processArguments(argStr); 
    receivedInput = true; 
} 

処理:
私はグローバル変数を持っています。そのコールバックで、私はメッセージを受信したかどうかを確認します。

if (receivedInput) 
{ 
    //set up timer to fire again in 10 seconds 
    receivedInput = false; 
} 
else 
    exit(1); 

安全ですか?スレッド2の読み込みでは、条件がtrueまたはfalseのいずれかに評価されるため、問題はないと思います。しかし、両方のスレッドが同時にreceiveInputを設定しようとするとどうなるかはわかりません。また、タイマーを入力を待つ時間よりも3倍長くして、競合状態が心配していないようにしました。

編集: これを解決するために、receivedInputとboost :: shared_lockを設定するときにboost :: unique_lockを使用しました。これはreceivedInputを読み込むときに使用しました。私は例を使用しましたhere

+2

¤安全かどうか疑問に思うなら、そうではありません。何かが技術的に安全であるかどうかに関係なく、状況を理解することができなければ短時間で始めても完璧であってもバグが発生します。コードは事実上安全ではありませんが、事実上安全です。たとえば、技術的には、「チェック」スレッドは「if」で中断され、「input」スレッドは7行で処理される可能性があります。実際には起こることはありませんが、Bad Things™*のようなコードで実現します。 :-)乾杯&乾杯。 –

答えて

5

これは基本的に安全ではありません。スレッド1がtrueからreceivedInputに書き込まれた後、スレッド2に新しい値が表示されることは保証されません。たとえば、コンパイラは、if条件として使用されるとき、またはレジスタにキャッシングするときに、receivedInputの値に関する特定の前提を設定してコードを最適化することができるため、メインメモリが実際に読み取られる保証はありません条件が評価される場合。また、コンパイラとCPUの両方が、最適化のために読み書きの順序を変更する可能性があります。例えば、truegetLine()processArguments()の前にreceivedInputに書き込まれます。

また、同期のタイミングに頼ることは、各スレッドが所定の時間間隔内に取得するCPU時間の量や、すべて。

よくある間違いは、receivedInputvolatileとすることが役立ちます。実際には、volatileは、(例えばレジスタにキャッシュされる代わりに)値が実際にメインメモリに読み書きされ、変数の読み書きが互いに順序付けられていることを保証します。ただし、変数volatileの読み取りと書き込みが他の命令に対して順序付けされていることを保証するものではありません。

期待どおりに機能するには、メモリバリアや適切な同期メカニズムが必要です。

1

スレッディング基準を確認する必要があります。 POSIXスレッドについて言えば、これは明示的に未定義の動作です。つまり、あるスレッドが別のスレッドにアクセスしている間にオブジェクトにアクセスすることはできません。 何でもが起こる可能性があります。

+2

2011年9月現在、あなたのスレッディング標準はおそらくC++標準かもしれません! –

+0

@SteveJessop私はそれについて忘れてしまった! –

0

あなたのスレッドが独立したコードブロックを制御するためにreceivedInputの値を使用しますが、互いに同期していない場合は、1つの簡単な解決策があります:

がreceivedInput前に、「揮発性」を追加するので、コンパイラはしないだろうが、スレッドがreceivedInputの値を共有するのを防ぐ最適化。

+2

私はあなたが新しく、あなたが去ることを望んでいないので-1にしたくありませんが、マルチスレッドが普及するためには「揮発性」が有用であるという誤解を望んでいません。これは有用ではなく、「揮発性」はスレッド化や同期化の方法とは無関係です。 – GManNickG

+0

ご意見ありがとうございます。はい、私はここで間違いを犯しました.2つのスレッドは同じ変数に新しい値を割り当てます。ここでは同期が必要です。しかし、揮発性は確実にマルチスレッドに関係しています。 "一般的に言えば、volatileキーワードは、変数の値が"自分で "変更できないと想定しているコードに対して、コンパイラが最適化を適用しないようにするためのものです(wikipediaから再確認します):) – xiesusu

+1

マルチスレッド化は、変数に対する最適化を無効にすること以上のものです。 – GManNickG

関連する問題