使用volatile在.NET中的线程之间进行单向通信

Jer*_*emy 6 .net c# multithreading synchronization

我已经阅读了很多关于这个主题的帖子,我想我终于明白了这个volatile关键词在C#中是如何运作的.我仍然想在这里问一下,以确保我理解正确的概念.请考虑以下代码:

class ThreadWrapper
{
  public bool Enabled { get; set; }

  private void ThreadMethod()
  {
    while (Enabled) { // ... Do work }
  }
}
Run Code Online (Sandbox Code Playgroud)

根据我的理解,如果要设置另一个线程Enabled=false,原始线程可能不会立即(或者可能永远?)看到此更改.为了确保编译器不优化对Enabled属性的访问并依赖缓存值,更改代码如下所示应该解决问题.

  public bool Enabled { get {return mEnabled;} set {mEnabled=value;} }
  private volatile bool mEnabled;
Run Code Online (Sandbox Code Playgroud)

现在,只要读取Enabled值,就可以保证获得最新值,对吗?如果是这样,我应该能够将它用作简单的信号或标志(就像我上面的那样).

作为另一个例子,请考虑以下事项:

class C
{
  private volatile int i;
  private volatile bool enabledA;
  private volatile bool enabledB;

  void ThreadA()
  {
    i = 0; // Reset counter
    while (enabledA)
    {
      // .. Do some other repeated work
      if (i > 100)
      {
        // .. Handle threshold case
      }
    }
  }

  void ThreadB()
  {
    while (enabledB)
    {
      // .. Do work
      if (condition) // Some condition occurs that we want to count
      {
        i++;
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

对于像这样简单的线程间通信,volatile这里是否令人满意?我知道这i++不是一个原子操作,但如果一个线程正在进行所有递增而另一个只是想读取它以查看它是否达到某个阈值,我们没关系吗?

编辑:我当然在事后发现了另一个类似的问题和详细的答案 .

ros*_*dia 5

我相信你是对的.

MSDN关于该volatile关键字的文章在其示例中使用了这种相同的技术.