'lock(this)'是否适合同步每个成员函数?

时间:2011-01-16 13:45:53

标签: c# locking this

我有一个Singleton类,它高度依赖于它用作数据库的XML文件。在构造函数中,会读取XML文件,FileSystemWatcher正在监视任何进一步的更改。

现在,如果发生任何更改,我将再次从XML文件中读取数据,但此时应该可以访问非类函数,直到重新加载XML文件。

我的问题是我可以简单地使用this作为同步对象(在重新加载XML文件时)并且不对函数进行任何更改,而不是在每个函数上放置一个大的lock

3 个答案:

答案 0 :(得分:5)

最好避免使用

lock(this) - 有一个边缘情况,其他一些不相关的代码也可以锁定它,甚至可能导致死锁。

更好的方法是:

private readonly object lockObj = new object();

然后lock(lockObj) - 因为这是私有的,你可以避免这种边缘情况。

另一种策略是将所有数据加载到不可变的封装对象中;然后你可以通过更新单个引用来交换所有内容;并且保证引用赋值是原子的。这允许:

private SomeModel model;
public void Refresh() {
     SomeModel newModel = new ...
     // fully load etc
     ...
     model = newModel;
}

如果您始终拍摄快照,则效果最佳,即取代

var foo = model.Foo;
var bar = model.Bar;

您使用:

var snapshot = model;
var foo = snapshot.Foo;
var bar = snapshot.Bar;

从现在开始,我们知道Foo和Bar来自同一型号。

答案 1 :(得分:5)

lock上不要this。永远。这是因为您无法控制的代码可能会锁定您的对象并导致很难检测到死锁情况。

相反,请使用专用的lock对象:

private readonly object locker = new object();

然后:

lock(locker) {
   // something something
}

由于locker被标记为private,因此您无需担心锁定对象的对象外部的代码。

答案 2 :(得分:-1)

如果观察者是唯一的作家,而您的对象只是读者,那么ReaderWriterLock可能会更好。请务必阅读备注部分。