3

同様の質問をいくつか読みましたが、そこに記載されている状況はもう少し複雑です。

ヒープと2つのスレッドのようにbool b初期化されています。falseでの操作はわかりますboolsnot atomic、最後まで質問を読んでください。

最初のスレッドは一b = true度しか設定できず、他には何もしません。2 番目のスレッドbがループをチェックし、それtrueが何らかのアクションを実行するかどうかを確認します。

保護するために何らかの同期メカニズム (ミューテックスなど) を使用する必要がありますbか? そうしないとどうなりますか?を使用intsすると、同時に読み取りと書き込みを行うと、明らかに任意の値を取得できます。しかし、 とboolsがあるだけtrueで、の代わりにfalse一度取得してもかまいません。ポテンシャルですか?falsetrueSIGSEGV

4

5 に答える 5

7

データ競合により、未定義の動作が発生します。標準に関する限り、準拠する実装は segfault を許可されています。

b実際には、主な危険性は、同期がないと、コンパイラーがリーダーループ内のコードを十分に観察して「決して変化しない」と判断し、値の最初の読み取り以外のすべてを最適化することです。これができるのは、ループ内に同期がないことを観察した場合、値への書き込みがデータ競合になることがわかっているためです。オプティマイザは、プログラムが未定義の動作を引き起こさないと想定することが許可されているため、他のスレッドからの書き込みがないと想定することが許可されています。

bとしてマークするvolatileと、実際にはこの特定の最適化が妨げられますが、volatileオブジェクトのデータ競合でさえ未定義の動作です。オプティマイザーが「認識できない」コードを呼び出すと、実際には最適化が妨げられます。これは、そのコードがb. もちろん、リンク時/プログラム全体の最適化では、コンパイル時のみの最適化よりもオプティマイザーが認識できないものは少なくなります。

とにかく、ソフトウェアで最適化が行われないようにしても、一貫性のないキャッシュを備えたシステムのハードウェアで同様のことが起こるのを防ぐことはできません (少なくとも、私は主張します: 他の人は、これは正しくなく、volatileアクセスが必要であると主張します)。一部の実装はそのように動作します)。標準の内容について質問している場合、ハードウェアが古いキャッシュを無期限に表示するかどうかは問題ではありません。動作は未定義のままであり、この特定の最適化が問題であるかどうかに関係なく、実装によってコードが壊れる可能性があるためです。それはそれを壊します。

于 2012-10-30T09:00:55.990 に答える
3

The problem you might get is that we don't know how long it takes for the reader thread to see the changed value. If they are on different CPUs, with separate caches, there are no guarantees unless you use a memory barrier to synchronize the caches.

On an x86 this is handled automatically by the hardware protocol, but not on some other systems.

于 2012-10-30T09:03:11.873 に答える
2

保護するために何らかの同期メカニズム (ミューテックスなど) を使用する必要がありますbか?

そうしないと、データ競合が発生します。データ競合のあるプログラムの動作は未定義です。この質問に対する答えは、「プログラムに明確な動作を持たせたいですか?」という質問に対する答えと同じです。

そうしないとどうなりますか?

理論的には、何でも起こり得ます。それが未定義の動作の意味です。発生する可能性が最も高い悪いことは、「2 番目のスレッド」がtrue値を認識しない可能性があることです。

コンパイラは、プログラムにデータ競合がないと想定できます (動作が標準で定義されていない場合、そうでないかのように動作しても問題ありません)。2 番目のスレッドは値 を持つ変数からしか読み取りをfalse行わず、それらの読み取りに影響を与える同期がないため、論理的な結論として、値は決して変化せず、したがってループは無限になります。(そして、いくつかの無限ループは、C++11 では未定義の動作をします!)

于 2012-10-30T09:01:33.800 に答える
0

いくつかの代替ソリューションを次に示します。

  1. Mutexを使用してください。詳細は、上記の他の回答で説明されています。

  2. 同時読み取りと書き込みを管理/保護する読み取り/書き込みロックの使用を検討してください。pthread libは、実装を提供します:pthread_rwlock_t

  3. アプリケーションの動作に応じて、条件変数(pthread lib impl:pthread_cond_t)の使用を検討してください。これは事実上、あるスレッドから別のスレッドへのシグナルであり、whileループとboolチェックを削除できる可能性があります。

于 2012-10-30T09:47:20.727 に答える
-2

ブール値を volatile にするだけで十分です (x86 アーキテクチャの場合)。ミューテックスは必要ありません。

volatile bool b;
于 2012-10-30T09:07:45.177 に答える