c# – 内存模型和ThreadPool
我有一个类NonVolatileTest:
public class NonVolatileTest { public bool _loop = true; } 我有两个代码示例: 1: private static void Main(string[] args) { NonVolatileTest t = new NonVolatileTest(); Task.Run(() => { t._loop = false; }); while (t._loop) ; Console.WriteLine("terminated"); Console.ReadLine(); } 2: private static void Main(string[] args) { NonVolatileTest t = new NonVolatileTest(); Task.Run(() => { t._loop = false; }); Task.Run(() => { while (t._loop) ; Console.WriteLine("terminated"); }); Console.ReadLine(); } 在第一个例子中,所有工作都按预期工作,而’while’周期永远不会终止,但在第二个例子中,所有工作据称’_loop’字段都是不稳定的. 为什么? PS. 假设: 这个’bug’可能与TaskScheduler有关.我认为,在JIT为编译和运行完成第二个任务之前,第一个任务已经完成,因此JIT获取了更改的值. 解决方法
根据
C# 5 specification(并且在注释的C#4规范中可以找到相同的段落),在10.5.3节 – 易失性字段中,这表示:
(我的重点) 所以这被证明是不可预测的(也就是你的控制之外). 这两段代码行为不同的事实可归结为将代码提升到生成对象上的方法(用于闭包)而不是提升它的区别. 我的心灵代码阅读眼睛告诉我,这是第一种情况可能发生的情况: >任务已启动,但在调用委托中的实际代码之前,这会产生开销 在第二种情况下,由于第一种情况有效地“通过一些对象引用读取变量”而第二种情况有效地“通过该引用读取变量”,这可能会产生差异,因此上述情况略有改变. 但这里真正的答案是你很容易使用优化器并编写不可预测的代码. 不要惊慌,结果也是不可预测的. 对代码进行微小的看似无关的更改可以使优化器以不同的方式执行操作. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |