25 c# multithreading
这个问题不是关于竞争条件,原子性,或者为什么要在代码中使用锁.我已经知道了.
更新:我的问题不是"存在易失性存储器的奇怪现象"(我知道它确实存在),我的问题是"没有.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
}
}
}
Run Code Online (Sandbox Code Playgroud)
Mar*_*ell 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);
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
Main exit
Run Code Online (Sandbox Code Playgroud)
但仍然在满CPU运行; 请注意,此时stopping已设定true.的ReadLine是,这样的过程不会终止.优化似乎取决于循环内代码的大小(因此i++).它只能在"发布"模式下工作.添加volatile,一切正常.