タグ付けされた質問 「volatile」

Volatileは、「独自に変更できる」データストレージ領域(オブジェクト、フィールド、変数、パラメーター)を定義するために使用される修飾子であり、一部のコードジェネレーターの最適化を許可しません。この修飾子を認識するすべての言語ではありませんが、そのようなデータへのアクセスはスレッドセーフです。

8
.NETのダブルチェックロックでの揮発性修飾子の必要性
複数のテキストによると、.NETでダブルチェックロックを実装する場合、ロックしているフィールドには揮発性修飾子を適用する必要があります。しかし、なぜ正確に?次の例を検討します。 public sealed class Singleton { private static volatile Singleton instance; private static object syncRoot = new Object(); private Singleton() {} public static Singleton Instance { get { if (instance == null) { lock (syncRoot) { if (instance == null) instance = new Singleton(); } } return instance; } } …
85 c#  singleton  volatile 

3
コンパイラーはローカルvolatileを定数フォールドできますか?
この単純なコードを考えてみましょう: void g(); void foo() { volatile bool x = false; if (x) g(); } https://godbolt.org/z/I2kBY7 への潜在的な呼び出しgccもclang最適化もされていないことがわかりgます。これが私の理解で正しいです:抽象マシンは、と仮定することでvolatile一定の折りので変数は、(例えば、ハードウェア・マッピングされたことに起因する)いつでも変更される可能性falseに初期化をifチェックは間違っているだろう。 しかし、MSVCはへの呼び出しをg完全に排除します(volatileただし、読み取りと書き込みを維持します!)。これは標準に準拠した動作ですか? 背景:デバッグ出力をオンザフライでオン/オフできるようにするために、この種のコンストラクトを時々使用します:コンパイラは常にメモリから値を読み取る必要があるため、デバッグ中に変数/メモリを変更すると、それに応じて制御フローが変更されます。MSVC出力は値を再読み取りしますが、それを無視します(たぶん、定数の折りたたみやデッドコードの除去のため)、これはもちろん、ここでの私の意図を無効にします。 編集: 読み取りと書き込みの排除については、volatileここで説明します。コンパイラーがローカルの揮発性変数を最適化することを許可されていますか?(ネイサンに感謝!)標準は、これらの読み取りと書き込みが発生する必要があることを十分に明確に考えています。しかし、その議論は、コンパイラーがそれらの読み取りの結果を当然のこととして受け取り、それに基づいて最適化することが合法かどうかをカバーしていません。私はこれが標準では不十分/不特定であると思いますが、誰かが私を間違っていると証明したら私は幸せです。 もちろんx、問題を回避するために非ローカル変数を作成することもできます。この質問は、好奇心から外れています。


3
「揮発性」は、マルチコアシステムのポータブルCコードで何かを保証しますか?
見た後、束 の 他の 質問 と その 回答を、私はという印象を得るCで「揮発性」というキーワードが正確に何を意味するのかには広範な合意はありませんが。 標準自体でさえ、誰もがそれが何を意味するのかについて合意するのに十分明確ではないようです。 他の問題の中で: それはあなたのハードウェアとあなたのコンパイラに依存して異なる保証を提供するようです。 コンパイラの最適化には影響しますが、ハードウェアの最適化には影響しません。そのため、独自のランタイム最適化を行う高度なプロセッサでは、コンパイラが防止したい最適化を防止できるかどうかさえ明確ではありません。(一部のコンパイラーは、一部のシステムで一部のハードウェア最適化を防止するために命令を生成しますが、これは決して標準化されていないようです。) 問題を要約すると、「大量に読み取った後」「揮発性」が次のようなことを保証しているように見えます。値は、レジスタからだけでなく、少なくともコアのL1キャッシュにも、同じ順序で読み書きされます。読み取り/書き込みがコードに表示されます。しかし、これは役に立たないようです。レジスタからの読み取り/レジスタへの書き込みは同じスレッド内ですでに十分ですが、L1キャッシュとの調整は、他のスレッドとの調整に関してそれ以上何も保証しません。L1キャッシュとだけ同期することがいつ重要になるかは想像できません。 USE 1 揮発性の広く合意された使用は、ライトを(直接、ハードウェアで)制御するメモリ内のビットのように、特定のメモリ位置がI / O機能にハードウェアでマッピングされている古いシステムまたは組み込みシステムであるようです、またはキーボードのキーが押されているかどうかを通知するメモリ内のビット(ハードウェアによって直接キーに接続されているため)。 と思われる「利用1」とは、そのターゲットのマルチコアシステムを含んポータブルなコードでは発生しません。 USE 2 「use 1」とそれほど変わらないのは、割り込みハンドラー(ライトの制御やキーからの情報の保存など)によっていつでも読み書きできるメモリです。しかし、すでにこのため、システムによっては、割り込みハンドラが 独自のメモリキャッシュを備えた別のコアで実行される可能性があり、「揮発性」はすべてのシステムでキャッシュの一貫性を保証しないという問題があります。 したがって、「use 2」は「volatile」が提供できる範囲を超えているようです。 USE 3 他に議論の余地のない唯一の用途は、コンパイラーが認識しない同じメモリーを指している同じメモリーを指すさまざまな変数を介したアクセスの誤最適化を防ぐことです。しかし、人々がそれについて話していないので、これはおそらく議論の余地がないだけです-私はそれについての言及を1つだけ見ました。また、C標準では、「異なる」ポインター(関数への異なる引数など)が同じ項目または近くの項目を指す可能性があることをすでに認識しており、コンパイラーがそのような場合でも機能するコードを生成する必要があることをすでに指定しています。しかし、私はこのトピックを最新(500ページ)の標準ですぐに見つけることができませんでした。 では「use 3」はまったく存在しないのでしょうか。 したがって、私の質問: 「揮発性」は、マルチコアシステムのポータブルCコードで何かを保証しますか? 編集-更新 最新の標準を参照した後、答えは少なくとも非常に制限されているように見えます: 1.標準は、特定のタイプ "volatile sig_atomic_t"の特別な扱いを繰り返し指定しています。ただし、この規格では、マルチスレッドプログラムでシグナル関数を使用すると、未定義の動作が発生することも規定されています。したがって、この使用例は、シングルスレッドプログラムとそのシグナルハンドラ間の通信に限定されているようです。 2.この規格では、setjmp / longjmpに関連する「揮発性」の明確な意味も規定されています。(重要なコードの例は、他の質問と回答に記載されています。) したがって、より正確な質問は次のようになります 。「揮発性」は、(1)シングルスレッドプログラムがシグナルハンドラから情報を受信できるようにする、または(2)setjmpを許可することを除いて、マルチコアシステムのポータブルCコードで何でも保証しますかsetjmpとlongjmpの間で変更された変数を表示するコード? これははい/いいえの質問です。 「はい」の場合、「揮発性」が省略された場合にバグになるバグのないポータブルコードの例を示すことができればすばらしいでしょう。「いいえ」の場合、マルチコアターゲットの場合、これら2つの非常に特殊なケース以外では、コンパイラーは「揮発性」を無視してもかまいません。

1
このC ++ AtomicInt実装は正しいですか?
前提:私はARM組み込み(ほとんどベアメタル)環境で作業していますが、C ++ 11(も)さえ使用できないので、「標準のC ++のみを使用するstd::atomic<int>」などの回答は避けてください:できません。std::atomic<int> このAtomicIntのARM 実装は正しいですか?(ARMアーキテクチャがARMv7-Aであると想定) 同期の問題が発生していますか?それはvolatile必要/便利? // File: atomic_int.h #ifndef ATOMIC_INT_H_ #define ATOMIC_INT_H_ #include <stdint.h> class AtomicInt { public: AtomicInt(int32_t init = 0) : atom(init) { } ~AtomicInt() {} int32_t add(int32_t value); // Implement 'add' method in platform-specific file int32_t sub(int32_t value) { return add(-value); } int32_t inc(void) { …

4
揮発性読み取りを取り除くためにJavaでメモリバリアをエミュレートする
同時にアクセスされるフィールドがあり、何度も読み取られ、めったに書き込まれないと仮定します。 public Object myRef = new Object(); スレッドT1がmyRefを1分に1回別の値に設定し、他のN個のスレッドがmyRefを数十億回連続して同時に読み取るとします。myRefが最終的にすべてのスレッドに表示されることだけが必要です。 簡単な解決策は、AtomicReferenceまたは単にvolatileを次のように使用することです。 public volatile Object myRef = new Object(); ただし、afaikの揮発性読み取りではパフォーマンスコストが発生します。非常に小さいことはわかっていますが、これは実際に必要なものというよりは、私が不思議に思っているようなものです。したがって、パフォーマンスに関係なく、これは純粋に理論的な質問であると想定しましょう。 つまり、質問は次のようになります。書き込みサイトで何かを行うことによって、書き込みがほとんどない参照の揮発性読み取りを安全にバイパスする方法はありますか? いくつか読んだ後、メモリの壁が私が必要とするものであるように見える。したがって、このような構成が存在する場合、私の問題は解決されます。 書く バリアを呼び出す(同期) すべてが同期され、すべてのスレッドに新しい値が表示されます。(読み取りサイトでの永続的なコストがないと、キャッシュが同期されるため、古くなったり、一時的なコストが発生する可能性がありますが、その後は通常のフィールドに戻り、次の書き込みまで続きます)。 そのような構造はJava、または一般にありますか?この時点で私は仕方がありませんが、このようなものが存在する場合、それを維持するはるかに賢い人々によってすでにアトミックパッケージに組み込まれていると思います。(不定期に頻繁に読み取りと書き込みを行う必要はなかったのではないでしょうか?)それで、私の考えに何か問題があり、そのような構成はまったく不可能ですか? いくつかのコードサンプルが同様の目的で「揮発性」を使用し、それが契約前に発生することを利用するのを見てきました。別の同期フィールドがあります。例: public Object myRef = new Object(); public volatile int sync = 0; そしてスレッド/サイトを書く時: myRef = new Object(); sync += 1 //volatile write to emulate barrier これが機能するかどうかはわかりませんが、x86アーキテクチャでのみ機能すると主張する人もいます。JMSの関連セクションを読んだ後、その揮発性書き込みがmyRefの新しい値を確認する必要があるスレッドからの揮発性読み取りと結合されている場合にのみ、動作することが保証されていると思います。(したがって、揮発性の読み取りを取り除きません)。 …
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.