いくつかのソース コードを確認していますが、次のコードはスレッド セーフかどうか疑問に思っていました。コンパイラまたは CPU 命令/読み取りの並べ替えについて聞いたことがあります (分岐予測と関係がありますか?)。以下の Data->unsafe_variable 変数は、別のスレッドによっていつでも変更できます。
私の質問は次のとおりです: コンパイラ/CPU が読み取り/書き込みをどのように並べ替えるかによって、以下のコードで Data->unsafe_variable を 2 回フェッチできるようになる可能性はありますか? (2 番目のスニペットを参照)
注:最初のアクセスについては心配していません。「if」を通過しない限り、データはそこにある可能性があります。「if」の後にデータが別の時間にフェッチされる可能性が心配です。ここで volatile へのキャストが二重フェッチを防ぐのに役立つかどうかも疑問に思っていましたか?
int function(void* Data) {
// Data is allocated on the heap
// What it contains at this point is not important
size_t _varSize = ((volatile DATA *)Data)->unsafe_variable;
if (_varSize > x * y)
{
return FALSE;
}
// I do not want Data->unsafe_variable to be fetch once this point reached,
// I want to use the value "supposedly" stored in _varSize
// Would any compiler/CPU reordering would allow it to be double fetched?
size_t size = _varSize - t * q;
function_xy(size);
return TRUE;
}
基本的に、セキュリティ上の理由から、プログラムがこのように動作することは望ましくありません。
_varSize = ((volatile DATA *)Data)->unsafe_variable;
if (_varSize > x * y)
{
return FALSE;
}
size_t size = ((volatile DATA *)Data)->unsafe_variable - t * q;
function10(size);
ここでは単純化していますが、mutex は使用できません。しかし、揮発性キャストの代わりに最初の行の後に _ReadWriteBarrier() または MemoryBarrier() を使用する方が安全でしょうか? (VSコンパイラ)
編集:コードにもう少しコンテキストを与えます。