ほとんどの人は、リリース モードでビルドするときに発生する次の問題を認識していると思います (コードは C# の Threadingから取得)。
static void Main()
{
bool complete = false;
var t = new Thread (() =>
{
bool toggle = false;
while (!complete) toggle = !toggle;
});
t.Start();
Thread.Sleep (1000);
complete = true;
t.Join(); // Blocks indefinitely
}
の値をキャッシュするコンパイラの最適化によりcomplete
、子スレッドが更新された値を見ることができなくなります。
ただし、上記のコードを少し変更します。
class Wrapper
{
public bool Complete { get; set; }
}
class Test
{
Wrapper wrapper = new Wrapper();
static void Main()
{
var test = new Test();
var t = new Thread(() =>
{
bool toggle = false;
while (!test.wrapper.Complete) toggle = !toggle;
});
t.Start();
Thread.Sleep(1000);
test.wrapper.Complete = true;
t.Join(); // Blocks indefinitely
}
}
volatile
、メモリフェンス、または暗黙のフェンスを導入するその他のメカニズムを使用せずに、問題を解消します (つまり、子スレッドは 1 秒後に終了できます) 。
完了フラグの追加されたカプセル化は、スレッド間の可視性にどのように影響しますか?