共享内存是否可以在某个线程中更新,而其值对主线程仍然不可见?

发布于 2024-11-13 19:21:43 字数 936 浏览 0 评论 0原文

我正在阅读这篇关于易失性的文章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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

自我难过 2024-11-20 19:21:43

易失性可以防止(除其他外)重新排序,因此如果没有易失性,它可以作为边缘条件(在某些硬件上)以不同的顺序写入它们,从而允许标志为真,即使结果为 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文