共享内存是否可以在某个线程中更新,而其值对主线程仍然不可见?
我正在阅读这篇关于易失性的文章C# 中的字段。
using System;
using System.Threading;
class Test
{
public static int result;
public static volatile bool finished;
static void Thread2() {
result = 143;
finished = true;
}
static void Main() {
finished = false;
// Run Thread2() in a new thread
new Thread(new ThreadStart(Thread2)).Start();
// Wait for Thread2 to signal that it has a result by setting
// finished to true.
for (;;) {
if (finished) {
Console.WriteLine("result = {0}", result);
return;
}
}
}
}
正如您所看到的,主线程中有一个循环,等待设置易失性标志,以便打印“结果”,该结果在设置标志之前被分配给 143。它在解释中说,如果该标志没有被声明为 volatie 那么
商店允许这样做 使结果对主要可见 商店完成后的线程
我在这里错过了什么吗?即使它不是易失性的,为什么程序会打印出 0。
I was reading this article about volatile fields in C#.
using System;
using System.Threading;
class Test
{
public static int result;
public static volatile bool finished;
static void Thread2() {
result = 143;
finished = true;
}
static void Main() {
finished = false;
// Run Thread2() in a new thread
new Thread(new ThreadStart(Thread2)).Start();
// Wait for Thread2 to signal that it has a result by setting
// finished to true.
for (;;) {
if (finished) {
Console.WriteLine("result = {0}", result);
return;
}
}
}
}
As you can see, there's a loop in the main thread that waits for the volatile flag to be set in order to print 'result', which is assigned to 143 before the flag is set. It says in the explanation that if the flag was not declared as volatie then
it would be permissible for the store
to result to be visible to the main
thread after the store to finished
Did I miss something here? Even if it was not volatile, how come the program will ever printout 0.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
易失性可以防止(除其他外)重新排序,因此如果没有易失性,它可以作为边缘条件(在某些硬件上)以不同的顺序写入它们,从而允许标志为真,即使结果为 0 - 对于一小部分时间。然而,更可能的情况是,如果没有易失性,热循环会将标志缓存在寄存器中,并且即使它已被更改,永远不会退出。
实际上,这不是处理并发的好方法,特别是像这样的热循环确实非常有害。在大多数常见情况下,首选锁或某种类型的等待句柄。或者,如果您的 .NET 版本是最新的,那么任务将是理想的选择。
Volatile prevents (among other things) re-ordering, so without volatile it could as an edge condition conceivably (on some hardware) write them in a different order, allowing the flag to be true even though result is 0 - for a tiny fraction of time. A much more likely scenario, though, is that without volatile the hot loop caches the flag in a register and never exits even though it has been changed.
In reality, this is not a good way to handle concurrency, and in particular a hot loop like that is really actively harmful. In most common cases, a lock or a wait-handle of some kind would be preferred. Or a Task would be ideal if you are up to date in your .NET versions.