这个问题不是关于竞争条件,原子性,或者为什么要在代码中使用锁.我已经知道了.
更新:我的问题不是"存在易失性存储器的奇怪现象"(我知道它确实存在),我的问题是"没有.NET运行时抽象,所以你永远不会看到它".
请参阅http://www.yoda.arachsys.com/csharp/threads/volatility.shtml 和关于字符串属性本身线程安全的第一个答案吗?
(它们实际上是同一篇文章,因为一个引用另一个.)一个线程设置bool而另一个线程循环永远读取bool - 那些文章声称读取线程可能缓存旧值并且从不读取新值,所以因此你需要一个锁(或使用volatile关键字).他们声称以下代码可能永远循环.现在我同意锁定变量是一种好习惯,但我无法相信.NET运行时会真正忽略内存值的变化,如文章所述.我理解他们关于易失性内存与非易失性内存的讨论,我同意他们在非托管中有一个有效的观点代码,但我无法相信.NET运行时将无法正确地抽象出来,以便下面的代码能够满足您的期望.这篇文章甚至承认代码"几乎可以肯定"有效(虽然不能保证),所以我就索赔要求BS.任何人都可以验证以下代码是否真的有效?是否有人能够得到一个案例(也许你不能总是重现它)这个失败的地方?
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 } } }
Marc Gravell.. 49
关键是:它可能有效,但不能保证按规范工作.人们通常遵循的是代码,这些代码适用于正确的原因,而不是通过编译器,运行时和JIT的混合组合工作,这可能会在框架版本,物理CPU,平台和x86之类的东西之间发生变化. 64.
理解记忆模型是一个非常复杂的领域,我并不认为自己是专家; 但人们谁是真正的专家在这方面向我保证,你所看到的行为是不能保证.
您可以发布任意数量的工作示例,但不幸的是,除了"它通常有用"之外,这并不是很多.这当然不能证明它是保证工作.它只需要一个反例来反驳,但发现它就是问题......
不,我没有一只手.
使用可重复的反例进行更新:
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); } }
输出:
Main exit
但仍然在满CPU运行; 请注意,此时stopping
已设定true
.的ReadLine
是,这样的过程不会终止.优化似乎取决于循环内代码的大小(因此i++
).它只能在"发布"模式下工作.添加volatile
,一切正常.
关键是:它可能有效,但不能保证按规范工作.人们通常遵循的是代码,这些代码适用于正确的原因,而不是通过编译器,运行时和JIT的混合组合工作,这可能会在框架版本,物理CPU,平台和x86之类的东西之间发生变化. 64.
理解记忆模型是一个非常复杂的领域,我并不认为自己是专家; 但人们谁是真正的专家在这方面向我保证,你所看到的行为是不能保证.
您可以发布任意数量的工作示例,但不幸的是,除了"它通常有用"之外,这并不是很多.这当然不能证明它是保证工作.它只需要一个反例来反驳,但发现它就是问题......
不,我没有一只手.
使用可重复的反例进行更新:
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); } }
输出:
Main exit
但仍然在满CPU运行; 请注意,此时stopping
已设定true
.的ReadLine
是,这样的过程不会终止.优化似乎取决于循环内代码的大小(因此i++
).它只能在"发布"模式下工作.添加volatile
,一切正常.