0

そう思うのは私だけでしょうか?[すぐに本当の質問です。]

それについての大きな混乱と、ミューテックスや他のロックメカニズムとの混合に加えて、スレッドセーフの状況を扱っているときは、 の使用を常に破棄する必要がvolatileあります。

volatilevolatile 「読み取り/書き込みの並べ替えやキャッシュを禁止します」が、これは、単一のオブジェクトにタグを付けるだけである限り、あまり役に立ちません(「通常の」オブジェクトではなくなるため、それを汚染します)。

このことを考慮:

Thread A            Thread B
reads vars
                    locks mutex (gets access)
locks mutex (waits)
                    writes some vars
                    releases mutex
reads vars again
releases mutex

ここで、コンパイラは 2 つのスレッド A の読み取りを最適化し、結果の一部をレジスタに保存する必要がある場合があります。あなたは、それらの vars を として宣言する必要があると言いますvolatile。は石のように透過的であり、型をサポートするためにコードの 50% を複製する必要があるvolatileため、すべてを としてフラグ付けしたくないと言います。あなた(volatilevolatile)ミューテックス(少なくともPOSIXミューテックス)のロックは、コンパイラーが認識して正しく管理するものであるか、世界を変える可能性のあるライブラリ(コンパイラーにアクセスできない)への呼び出しであるため、コンパイラーは想定しないそのような電話の後は何でも。私は、これは実装に依存しすぎており、非常に低レベルのものだと言っています (そして、日々のプログラミングのために開発ドキュメントを参照したくありません)。さらに悪いことに、何らかの理由で「外部ライブラリ」が正当な理由でコンパイラにアクセスできるようになった場合、突然変更される可能性があります(おそらく、作成者はヘッダーに含める必要があるテンプレートで関数を変換します...何でも) .

したがって、私の意見でvolatileは、非常に低レベルのもの(おそらくデバイスの読み取りですが、私はそのような分野では能力がありません)を除いて、まったく役に立たない(そして誤解を招く)ものです。

変数に関する仮定を破棄する必要があり、その後のすべての読み取りはメモリからの真の読み取りでなければならないことをコンパイラーに明示伝える別の方法の方がはるかに優れています。しかし、ダミーの外部関数を呼び出すよりも良いことは想像できません。それには、以前に概説したのと同じ問題があります。そうするエレガントな方法はありますか?

4

3 に答える 3

8

私は低レベルのものを扱っています。これが役立つ例を次に示します。

volatile uint32_t *foo = <<<a register on a pci device>>> 

複数回読むfooと、異なる結果が得られる可能性があります。これは、外部ソース (pci デバイス) が変更しているためです。たとえばfoo、現在の時刻を意味する場合があります。

また、私が に書いたときにfoo、結果とはほとんど関係がない可能性もあります。たとえば、いくつかのアラート ビットを格納するレジスタがあるとします。これらのビットに書き込み、クリアします。したがって、レジスタfooに value がある場合、レジスタに0x72書き込む0x2と、そのレジスタの結果の値が になる可能性があります0x70

volatileこれらのセマンティクスを使用できます。

于 2012-06-05T22:19:46.423 に答える
2

Volatile は、マルチスレッド コードの問題を魔法のように解決するためのものではありません。変数の値またはメモリ位置が、コンパイラ (または CPU でさえも) を知る方法がなくても変更できる場合に使用されます。

詳細な説明については、C++ の揮発性クラスを参照してください。

于 2012-06-05T22:20:53.127 に答える
2

新しい C 標準である C11 には、あなたが求めているものがあります。まず、スレッド モデルと、スレッドにまで及ぶ詳細な「以前に発生した」関係があります。そして、atomic_thread_fenceあなたが探していることを行う操作があります。

于 2012-06-05T22:21:16.313 に答える