布尔属性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;
}
}
}
你不一定需要锁,但是如果你想让一个线程明确地读取另一个线程写的值,你要么需要锁,要么需要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
关键字。
没有理由在这里设置锁。
在您的设计中使用锁可能是合适的,但这是否是正确的粒度是非常值得怀疑的。
你需要让你的设计线程安全,而不是单个属性(甚至是整个对象)。