布尔属性Getter和Setter锁定

本文关键字:Setter 锁定 Getter 属性 布尔 | 更新日期: 2023-09-27 18:03:51

为什么要像这样在布尔属性的getter和setter周围创建锁呢?

  private _lockObject = new object();
  private bool _myFlag;
  public bool MyFlag
  {
    get
    {
      lock (_lockObject)
      {
        return _myFlag;
      }
    }
    set
    {
      lock (_lockObject)
      {
        _myFlag = value;
      }
    }
  }

布尔属性Getter和Setter锁定

你不一定需要,但是如果你想让一个线程明确地读取另一个线程写的值,你要么需要锁,要么需要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.");
    }
}

程序可以终止,也可以不终止。这两种情况我都见过。不能保证"读取"线程将实际上从主存中读取 -它可以将stop的初始值放入寄存器中并永远使用它。我在现实中看到过这种情况。这在我现在的机器上不会发生,但在我的下一台机器上可能会发生。

根据问题中的代码将锁放入属性getter/setter中,将使该代码正确且其行为可预测。

关于这方面的更多信息,请参阅Eric Lippert的博客文章

bool类型的读写操作都是原子操作

然而,名称"flag"表示在某些情况发生之前,将有单独的线程进行读写操作。为了避免由于优化而导致的意外行为,您应该考虑在bool声明中添加volatile关键字。

没有理由在这里设置锁。

在您的设计中使用锁可能是合适的,但这是否是正确的粒度是非常值得怀疑的。

你需要让你的设计线程安全,而不是单个属性(甚至是整个对象)。