問題タブ [volatile]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
java - 揮発性の保証とアウトオブオーダー実行
重要な編集2つの割り当てが行われているスレッドの「前に起こる」について知っています。私の質問は、 「a」がまだnullである間に、別のスレッドが「b」をnull以外で読み取る可能性があるかどうかです。したがって、以前にsetBothNonNull(...)を呼び出したスレッドと同じスレッドからdoIt()を呼び出している場合、NullPointerExceptionをスローすることはできません。しかし、setBothNonNull(...)を呼び出すスレッドとは別のスレッドからdoIt()を呼び出す場合はどうなるでしょうか。
この質問はvolatile
キーワードとvolatile
保証に関するものであることに注意してください。キーワードに関するものではありません(したがって、解決する問題がないため、「同期を使用する必要があります」と答えないでください。単に保証synchronized
を理解したいだけです。volatile
(または保証の欠如)アウトオブオーダー実行に関して)。
volatile
コンストラクターによってnullに初期化される2つの文字列参照を含むオブジェクトがあり、2つの文字列を変更する方法は1つしかないとします。つまり、 setBoth(...)を呼び出し、後でそれらの参照を非に設定することしかできません。 null参照(コンストラクターのみがそれらをnullに設定できます)。
たとえば(これは単なる例であり、まだ質問はありません):
setBothNoNull(...)では、非nullパラメータ「a」を割り当てる行が非nullパラメータ「b」を割り当てる行の前に表示されます。
次に、これを行うと(もう一度、質問はありません。質問は次に来ます):
アウトオブオーダー実行のためにNullPointerExceptionが発生する可能性があることを理解していますか?
言い換えると、null以外の「b」を読み取ったためにnull以外の「a」を読み取るという保証はありませんか?
アウトオブオーダー(マルチ)プロセッサとvolatile
動作方法により、「a」の前に「b」を割り当てることができますか?
volatile
書き込みに続く読み取りは常に最後に書き込まれた値を参照することを保証しますが、ここには順序が正しくない「問題」がありますか?volatile
(繰り返しになりますが、「問題」は、問題を解決するためではなく、キーワードとJavaメモリモデルのセマンティクスを理解しようとすることを目的としています)。
c++ - C++での揮発性と可変
揮発性と可変性の違いについて質問があります。私は、2つの両方がそれが変更される可能性があることを意味していることに気づきました。ほかに何か?それらは同じものですか?違いは何ですか?それらはどこに適用できますか?なぜ2つのアイデアが提案されているのですか?それらを別の方法で使用する方法は?
どうもありがとう。
c++ - C ++の揮発性メンバー関数の目的は何ですか?
volatile
C ++のメンバー関数の目的は何ですか?
c# - Interlocked は C# の他のスレッドへの可視性を保証しますか、それとも volatile を使用する必要がありますか?
私は同様の質問への回答を読んできましたが、まだ少し混乱しています...アベルには素晴らしい回答がありましたが、これは私が確信していない部分です:
...変数 volatile を宣言すると、アクセスごとに volatile になります。この動作を他の方法で強制することは不可能であるため、volatile を Interlocked に置き換えることはできません。これは、他のライブラリ、インターフェイス、またはハードウェアが変数にアクセスしていつでも更新できるシナリオ、または最新バージョンが必要なシナリオで必要になります。
Interlocked
すべてのスレッドに対するアトミック操作の可視性は保証されますか?それとも、変更の可視性を保証するために値にキーワードを使用する必要がありvolatile
ますか?
これが私の例です:
更新:
私はスポーツが苦手で、元の例を変更したので、ここにもう一度示します。
c++ - なぜ「揮発性」がC++に寄生するのですか?
次のコードを検討してください。
これにより、次のエラーが発生しg++
ます。
p
私の意図は、揮発性にしたいということでした。ただし、の値を読み取った後は、アクセスが揮発性であるp
かどうかは関係ありません。なぜ揮発性であると宣言v
する必要があるのですか?v
もちろん、これは架空のコードです。p
実際の状況では、それはメモリの場所を指していると想像できますが、外部で変更されているので、後で外部で変更されたとしても、その時点で指してv
いた場所を指したいと思います。したがって、揮発性ですが、そうではありません。p
v = p
p
p
v
ちなみに、これがCとC ++の両方と見なされる場合の動作に関心がありますが、Cでは、これは警告のみを生成し、エラーは生成しません。
c++ - マルチスレッドの C または C++ プログラミングで volatile が有用と見なされないのはなぜですか?
最近投稿したこの回答に示されているようにvolatile
、マルチスレッド プログラミング コンテキストでのユーティリティ (またはその欠如) について混乱しているようです。
私の理解は次のとおりです。変数にアクセスするコードの制御フローの外部で変数が変更される可能性がある場合はいつでも、その変数は であると宣言する必要がありますvolatile
。シグナル ハンドラ、I/O レジスタ、および別のスレッドによって変更された変数はすべて、このような状況を構成します。
したがって、グローバルな intfoo
があり、foo
あるスレッドによって読み取られ、別のスレッドによって (おそらく適切なマシン命令を使用して) アトミックに設定される場合、読み取りスレッドは、シグナル ハンドラーによって微調整された変数を見るのと同じ方法でこの状況を認識します。外部ハードウェア条件によって変更されるため、foo
宣言する必要がありますvolatile
(または、マルチスレッドの状況では、おそらくより良い解決策であるメモリ フェンシング ロードでアクセスします)。
どのように、どこで間違っていますか?
c++ - スレッドセーフなコードを書くのに役立つように、volatile をユーザー定義型にすることができます
以前のいくつかの質問/回答で明確にされていますが、これはvolatile
マルチスレッドではなく、C++ メモリ モデルの可視状態に関連しています。
一方、Alexandrescu によるこの記事volatile
では、このキーワードをランタイム機能としてではなく、コンパイル時のチェックとして使用して、コンパイラがスレッド セーフではない可能性のあるコードを受け入れないように強制しています。この記事では、キーワードはrequired_thread_safety
、実際に意図されているvolatile
.
volatile
これは適切なの(乱用)使用ですか?このアプローチには、どのような落とし穴が隠されている可能性がありますか?
最初に頭に浮かぶのは、追加の混乱です。volatile
これはスレッド セーフとは関係ありませんが、より優れたツールがないため、それを受け入れることができました。
記事の基本的な簡略化:
variable を宣言すると、その変数volatile
に対してメンバー メソッドのみvolatile
を呼び出すことができるため、コンパイラは他のメソッドへのコードの呼び出しをブロックします。std::vector
インスタンスを as として宣言するvolatile
と、クラスのすべての使用がブロックされます。const_cast
要件を解放するために実行するロッキング ポインターの形でラッパーを追加すると、ロッキング ポインターをvolatile
介したすべてのアクセスが許可されます。
記事からの盗用:
ノート
最初のいくつかの回答が表示された後、最も適切な言葉を使用していない可能性があるため、明確にする必要があると思います。
の使用は、volatile
それが実行時に提供するもののためではなく、コンパイル時にそれが何を意味するかによるものです。つまり、const
キーワードがユーザー定義型でほとんど使用されていない場合、同じトリックをキーワードで引き出すことができますvolatile
。つまり、メンバー関数呼び出しをブロックできるキーワード (たまたま volatile と綴られている) があり、Alexandrescu はそれを使用して、コンパイラをだましてスレッドセーフでないコードのコンパイルに失敗させています。
コンパイル時に何をするかという理由ではなく、コンパイラに何をさせるかという理由でそこにある多くのメタプログラミングのトリックと私は考えています。
c++ - std::cout が揮発性ポインタを bool に変換するのはなぜですか?
volatile 型へのポインターを cout しようとすると、通常は cout が文字列を出力すると予想される volatile char ポインターであっても、代わりに単に '1' を取得します (ポインターが null でないと仮定します)。出力ストリーム operator<< は揮発性ポインターに特化したテンプレートだと思いますが、私の質問はなぜですか? この動作の動機となるユースケースは何ですか?
コード例:
出力:
c - gccが不揮発性変数のこのチェックを削除しないのはなぜですか?
この質問は主に学術的なものです。これが私にとって実際の問題を引き起こすからではなく、好奇心からお願いします。
次の誤ったCプログラムについて考えてみます。
ハンドラーがプログラムフローを中断するため、このプログラムは正しくrunning
ありません。したがって、いつでも変更できるため、宣言する必要がありますvolatile
。しかし、プログラマーがそれを忘れたとしましょう。
gcc 4.3.3は、-O3
フラグを使用して、ループ本体を(フラグを最初にチェックした後running
)無限ループにコンパイルします。
これは予想されていた。
while
次に、ループ内に次のような些細なことを入れます。
そして突然、gccはループ条件を最適化しなくなりました!ループ本体のアセンブリは次のようになります(ここでも-O3
):
running
ループを通過するたびにメモリから再ロードされることがわかります。レジスターにもキャッシュされません。どうやらgccは、の値running
が変更された可能性があると考えているようです。
では、なぜgccはrunning
、この場合の値を再チェックする必要があると突然判断するのでしょうか。