絶対。
x
はマークされておらず、volatile
自動保存期間と内部リンケージを持つローカル オブジェクトのように見え、プログラムはそれを変更しないため、2 つのプログラムは同等です。
C++03 と C++11 の両方で、非揮発性オブジェクトへのアクセスはプログラムの「副作用」とは見なされないため、これは as-if 規則によるものです。
[C++11: 1.9/12]:
volatile glvalue (3.10) で指定されたオブジェクトへのアクセス、オブジェクトの変更、ライブラリ I/O 関数の呼び出し、またはこれらの操作のいずれかを実行する関数の呼び出しはすべて、実行環境の状態の変化である副作用です。一般に、式 (またはサブ式) の評価には、値の計算 (glvalue 評価のためのオブジェクトの ID の決定と、prvalue 評価のためのオブジェクトに以前に割り当てられた値のフェッチを含む) と副作用の開始の両方が含まれます。ライブラリ I/O 関数の呼び出しが返されるか、揮発性オブジェクトへのアクセスが評価されると、呼び出し (I/O 自体など) または揮発性アクセスによって暗黙の外部アクションがある場合でも、副作用は完了したと見なされます。まだ完了していない可能性があります。
C++11 では、グローバルオブジェクトの値が 1 つのスレッドで変更され、その新しい値が別のスレッドで読み取られるようになります。
[C++11: 1.10/3]:
T
特定の時点でスレッドに表示されるオブジェクトの値は、以下のルールに従って、オブジェクトの初期値、 によってオブジェクトに割り当てられた値T
、または別のスレッドによってオブジェクトに割り当てられた値です。
ただし、これを行う場合、オブジェクトはアトミックではないため、次のようになります。
[C++11: 1.10/21]:
プログラムの実行にデータ競合が含まれているのは、異なるスレッドに競合する 2 つのアクションが含まれており、そのうちの少なくとも 1 つがアトミックではなく、どちらも他のスレッドの前に発生しない場合です。このようなデータ競合は、未定義の動作を引き起こします。
また、未定義の動作が呼び出されると、あらゆることが起こります。
ブートノート
[C++11: 1.10/25]:
実装では、アトミック操作または同期操作によって割り当てられた最後の値 (変更順序で) が、限られた期間内に他のすべてのスレッドに表示されるようにする必要があります。
繰り返しますが、この保証を得るには、オブジェクトがアトミック(たとえば ) でなければならないことに注意してください。std::atomic<bool>