スレッド上のキャッシュされた値は他のスレッドで行われた変更を無視できますか?
この質問は、C# スレッドが値をキャッシュして無視できるかどうかに焦点を当てています。その後、別のスレッドでその値に変更が加えられます。競合状態、アトミック性、およびロックの使用に関する一般的な知識にもかかわらず、この調査は、.NET ランタイムが揮発性メモリの問題を潜在的に抽象化する可能性があるシナリオを特にターゲットにしています。
一部の情報源は、次のコードで読み取りが行われていると主張しています。スレッドはブール変数の初期値を「停止中」にキャッシュし、その変更を決して検出しない可能性があり、無限ループにつながる可能性があります:
class BackgroundTaskDemo { private bool stopping = false; static void Main() { BackgroundTaskDemo demo = new BackgroundTaskDemo(); new Thread(demo.DoWork).Start(); Thread.Sleep(5000); demo.stopping = true; } static void DoWork() { while (!stopping) { // Do something here } } }
ただし、有効性はこの主張については争われている。批評家は、.NET ランタイムがメモリ値の変更を本当に無視するのかどうかを疑問視しています。彼らは、指定されたコードが「ほぼ確実に」動作すると指摘し、この主張には根拠がないことを暗示しています。
問題の核心は、その主張に記載されている動作が .NET 仕様によって保証されていないということです。ほとんどの場合に機能する可能性がありますが、すべての状況で機能することが保証されているわけではありません。メモリ モデルの分野の専門家は、そのような信頼性の低い結果に依存しないように警告しています。
さらに、コードが予測どおりに失敗する特定のシナリオを示す、検証可能な反例が提示されています。次の修正されたコードでは、問題を修正するために「stopping」が volatile として宣言されています。
using System.Threading; using System; static class BackgroundTaskDemo { // make this volatile to fix it private static bool stopping = false; static void Main() { new Thread(DoWork).Start(); Thread.Sleep(5000); stopping = true; Console.WriteLine("Main exit"); Console.ReadLine(); } static void DoWork() { int i = 0; while (!stopping) { i++; } Console.WriteLine("DoWork exit " + i); } }
volatile キーワードを指定せずに「release」モードで実行すると、コードは無限ループに入り、無期限に実行を続けます。 「stopping」が true に設定された後でも。ただし、「stopping」変数に「volatile」を追加すると問題が解決され、ループが意図したとおりに終了できるようになります。
結論としては、コードが機能しているように見えることはよくありますが、実際に機能するかどうかは保証できません。一貫して。堅牢で信頼性の高いマルチスレッド コードを実現するには、ロックまたは volatile キーワードの使用を強くお勧めします。
以上がC# スレッドはブール値をキャッシュし、他のスレッドでの後続の変更を無視できますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。