c# - EventWaitHandle 是否有任何隐式 MemoryBarrier?

标签 c# .net vb.net multithreading volatile

这个网站的新手,所以如果我没有以可接受的方式发帖请告诉我。

我经常按照下面的示例编写代码(为清楚起见,省略了 Dispose 之类的内容。)。我的问题是,是否需要如图所示的 volatile ?或者 ManualResetEvent.Set 是否像我读过 Thread.Start 那样具有隐式内存屏障?或者显式 MemoryBarrier 调用会比 volatiles 更好吗?还是完全错误?此外,据我所知,某些操作中的“隐式内存屏障行为”并未记录在案,这一事实令人非常沮丧,是否有这些操作的列表?

谢谢, 汤姆

:

class OneUseBackgroundOp
{

   // background args
   private string _x;
   private object _y;
   private long _z;

   // background results
   private volatile DateTime _a
   private volatile double _b;
   private volatile object _c;

   // thread control
   private Thread _task;
   private ManualResetEvent _completedSignal;
   private volatile bool _completed;

   public bool DoSomething(string x, object y, long z, int initialWaitMs)
   {
      bool doneWithinWait;

      _x = x;
      _y = y;
      _z = z;

      _completedSignal = new ManualResetEvent(false);

      _task = new Thread(new ThreadStart(Task));
      _task.IsBackground = true;
      _task.Start()

      doneWithinWait = _completedSignal.WaitOne(initialWaitMs);

      return doneWithinWait;

   }

   public bool Completed
   {
      get
      {
         return _completed;
      }
   }

   /* public getters for the result fields go here, with an exception
      thrown if _completed is not true; */

   private void Task()
   {
      // args x, y, and z are written once, before the Thread.Start
      //    implicit memory barrier so they may be accessed freely.

      // possibly long-running work goes here

      // with the work completed, assign the result fields _a, _b, _c here

      _completed = true;
      _completedSignal.Set();

   }

}

最佳答案

请注意,这是即兴的,无需仔细研究您的代码。我认为 Set 不会执行内存屏障,但我看不出这与您的代码有什么关系?似乎更重要的是 Wait 是否执行一个,它确实执行了。因此,除非我在专门查看您的代码的 10 秒内遗漏了什么,否则我认为您不需要 volatile 。

编辑:评论限制太多。我现在指的是 Matt 的编辑。

Matt 的评估做得很好,但他遗漏了一个细节。首先,让我们提供一些抛出的东西的定义,但这里没有阐明。

volatile 读取读取一个值,然后使 CPU 缓存无效。 volatile 写入会刷新缓存,然后写入值。内存屏障会刷新缓存,然后使其失效。

.NET 内存模型确保所有写入都是易变的。默认情况下,读取不是,除非进行了明确的 VolatileRead,或者在字段上指定了 volatile 关键字。此外,互锁方法强制缓存一致性,所有同步概念(Monitor、ReaderWriterLock、Mutex、Semaphore、AutoResetEvent、ManualResetEvent 等)在内部调用互锁方法,从而确保缓存一致性。

同样,所有这些都来自 Jeffrey Richter 的书“CLR via C#”。

我说,一开始,我认为 Set 不会执行内存屏障。然而,进一步思考里希特先生所说的,Set 将执行一个互锁操作,从而也将确保缓存一致性。

我坚持我最初的主张,即这里不需要 volatile。

编辑 2:看起来您正在构建一个“ future ”。我建议你看看 PFX ,而不是自己滚动。

关于c# - EventWaitHandle 是否有任何隐式 MemoryBarrier?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/681505/

相关文章:

c# - 抑制/禁用/解决 Visual Studio 构建警告

asp.net - 数据注释用于在记录之前清理请求和响应

c# - RadGrid 底部的水平滚动空白

vb.net - 如何通过 RF-433 模块从 VB 应用程序和 arduino 发送数据

c# - 为什么 net core 2.0 中的垃圾收集器不释放所有内存

c# - Silverlight:空数据网格

c# - 如何使用 .NET Framework 获取所有事件的 TCP 连接(无非托管 PE 导入!)?

c# - Task.Delay(-1) 是否有任何用例?

ASP.net 从 Google 重定向到移动网站

c# - 单击按钮后更改按钮的效果 WPF