2013-08-08 9 views
7

私は2つのスレッドからアクセスされる変数int fooを持っています。私は競合状態の問題(アクセスはミューテックスによって保護されており、すべての操作はアトミックであるか、競合状態から保護するための他の方法であれ)がないと仮定すると、(登録名の不足のために)ここで、コンパイラは変数が間に書き込まれず二度読まれている場合、それは同じ値であると仮定してもよい、などのように離れたものを「最適化する」ことがあります。スレッド間で変数を同期させるための `volatile`

while(foo) { // <-may be optimized to if(foo) while(1) 
    do-something-that-doesn't-involve-foo; 
} 

または

if(foo) // becomes something like (my assembly is very rusty): mov ebx, [foo]; cmp ebx, 0; jz label; 
    do-something-that-doesn't-involve-foo; 
do-something-else-that-doesn't-involve-foo; 
if(foo) // <-may be optimized to jz label2; 
    do-something; 

fooとしてvolatileと表示されていますか?あるスレッドからの変更が他のスレッドに到達することが保証されていますか?

そうでない場合は、これを行うには他にどのような方法がありますか?私はLinux/Windows(おそらく別々のソリューション)、C++ 11用のソリューションが必要です。

+0

私は、スレッドのためにvolatileをもう使用しないと言っている標準から引用符を見たことを思い出しました.C++では、私はそれを見つけようとします – aaronman

+3

http:// stackoverflow。com/questions/4557979/when-to-use-volatile-with-multi-threading –

+1

ここでの問題は「競合状態の問題がないと仮定します」です。これは** ENORMOUS **の前提です。 –

答えて

11

メモリバリアが必要です。

MemoryBarrier(); 

または

__sync_synchronize(); 

編集:私は興味深い部分を太字にしましたし、ここでのwikiの記事(http://en.wikipedia.org/wiki/Memory_barrier#cite_note-1)及び関連する基準(http://www.rdrop.com/users/paulmck/scalability/paper/whymb.2010.07.23a.pdf

へのリンクはこちらへの答えだていますあなたの別の質問(ウィキペディア): CおよびC++では、volatileキーワードは、CおよびC++プログラムがメモリマップされたI/Oに直接アクセスできるようにするためのものです。メモリマップされたI/Oは、一般的に、ソースコードで指定された読み取りと書き込みが、省略されていない正確な順序で行われることを要求します。コンパイラによる読取りおよび書込みの省略または順序変更は、プログラムとメモリマップI/Oによってアクセスされるデバイスとの間の通信を切断する。 CまたはC++コンパイラは、揮発性メモリの場所への読み書きを再整理したり、揮発性メモリの場所への読み書きを省略することはできません。 キーワードvolatileは、キャッシュ一貫性を強制するメモリバリアを保証しません。したがって、単独で「揮発性」の使用は、すべてのシステムおよびプロセッサ上でスレッド間通信のための変数を使用するには不十分である[1]

それは被験者に多大な説明を提供し、これをチェックアウト: http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-1-of-2 http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-2-of-2

9

アクセスがミューテックスによって保護されている場合は、心配する必要はありません。ここではvolatileというキーワードは無用です。ミューテックスは完全なメモリバリアであるため、外部から見えるアドレスを持つオブジェクトは、ミューテックスのロックやロック解除の呼び出しでキャッシュすることはできません。

+0

真。ミューテックスはキャッシュの整合性を確保します。 – MasterPlanMan

+0

明確にするために、キャッシュでは、マシンレベルのキャッシュだけでなく、レジスタ内の値のコンパイラのキャッシュも意味しました。 –

1

volatileキーワードは、もともと値がハードウェアによって変更可能であることを示すために導入されました。これは、ハードウェアデバイスにメモリマップレジスタまたはメモリバッファがある場合に発生します。適切なアプローチは、この目的のためだけに使用することです。

現代の同期言語構成および同期ライブラリはすべてこのキーワードを使用していません。アプリケーションレベルのプログラマも同じことをする必要があります。

関連する問題