布尔属性Getter和Setter锁定

Noo*_*oob 18 c# multithreading locking properties

你有没有理由在这个布尔属性的getter和setter周围创建锁?

  private _lockObject = new object();
  private bool _myFlag;
  public bool MyFlag
  {
    get
    {
      lock (_lockObject)
      {
        return _myFlag;
      }
    }
    set
    {
      lock (_lockObject)
      {
        _myFlag = value;
      }
    }
  }
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 24

好吧,你不一定需要 - 但如果你想要一个线程肯定读取另一个线程写的值,你需要锁或一个volatile变量.

我个人放弃了试图理解volatile的确切含义.我尽量避免编写自己的无锁代码,而是依靠真正了解内存模型的专家.

编辑:作为这可能导致的问题的一个例子,请考虑以下代码:

using System;
using System.Threading;

public class Test
{
    private static bool stop = false;

    private bool Stop
    {
        get { return stop; }
        set { stop = value; }
    }

    private static void Main()
    {
        Thread t = new Thread(DoWork);
        t.Start();
        Thread.Sleep(1000); // Let it get started
        Console.WriteLine("Setting stop flag");
        Stop = true;
        Console.WriteLine("Set");
        t.Join();
    }

    private static void DoWork()
    {
        Console.WriteLine("Tight looping...");
        while (!Stop)
        {
        }
        Console.WriteLine("Done.");
    }
}
Run Code Online (Sandbox Code Playgroud)

该计划可能会也可能不会终止.我看到两者都发生了.不能保证"读取"线程实际上会从主存储器中读取 - 它可以将初始值stop放入寄存器中,并且永远使用它.实际上,我已经看到了这种情况.它不会发生在我当前的机器上,但它可能会在我的下一台机器上发生.

根据问题中的代码将锁置于属性getter/setter中将使此代码正确并且其行为可预测.

有关这方面的更多信息,请参阅Eric Lippert撰写的这篇博客文章.

  • 嗨,乔恩,谢谢你的回应.我发现这篇文章很好地阐述了你的帖子...... http://igoro.com/archive/volatile-keyword-in-c-memory-model-explained/ (2认同)