由于它是一种小于或等于CPU架构的字大小的数据类型,所以您几乎不担心是否会出现数据损坏问题。写入和读取将是原子的。
虽然这不是问题。问题是,在某些情况下,该国旗的读者可能永远不会看到它改变为价值。这实际上很容易用以下代码来演示。您将需要使用Release配置进行编译,并在没有附加调试器的情况下运行它。您可能会发现该程序永远不会有效地证明该错误。
// * Must be compiled as RELEASE and ran outside of a debugger.
class Program
{
// Decorate with volatile to change the behavior.
static bool stop = false;
public static void Main(string[] args)
{
var t = new Thread(() =>
{
Console.WriteLine("thread begin");
bool toggle = false;
while (!stop)
{
toggle = !toggle;
}
Console.WriteLine("thread end");
});
t.Start();
Thread.Sleep(1000);
stop = true;
Console.WriteLine("stop = true");
Console.WriteLine("waiting...");
// The Join call should return almost immediately.
// With volatile it DOES.
// Without volatile it does NOT.
t.Join();
}
}
在您的具体情况下,这可能实际上是没有争议的。原因是作者是后台线程,读者是UI线程。这是至关重要的,因为内存屏障将保证在后台线程结束时写入被执行,这可能在hasLoad
设置为true
后立即生效。在UI线程方面,消息泵本身可能会注入一个你不知道的内存屏障。因此,每次您检查hasLoaded
的值(推测使用某种计时器)时,您可能会获得最新值。
无论如何,如果它的工作没有锁或使用volatile
它是这样做,只是偶然。帮你一个忙,并采取适当的保护措施,并锁定。
更好的是,使用Task
结合新的async
和await
关键字。如果做得正确,这可以完成,甚至不需要hasLoaded
标志,它也会看起来更优雅。
锁定会阻止对跨线程共享的资源执行并发操作。跨线程共享哪些资源,您认为您可能需要锁定? – 2014-08-29 18:35:34
变量本身。对不起,我以为我说得很清楚。我会很快回顾我的问题 – Haedrian 2014-08-29 18:36:14
只需使用[BackgroundWorker](http://msdn.microsoft.com/en-us/library/cc221403(v = vs.95).aspx)并等待它发射它RunWorkerCompleted事件 – Jonesopolis 2014-08-29 18:36:46