应该在属性上使用synclock吗?

时间:2010-11-25 00:31:03

标签: c# multithreading properties synclock

我一直在阅读,并且我是否应该在属性上使用synclock来得到相互矛盾的答案。

我有一个多线程应用程序,需要跨实例对象的线程获取/设置属性。它目前没有使用synclock实现,到目前为止我没有发现任何问题。我在常见的静态方法上使用synclock,但我想以线程安全的方式正确实现我的实例类。

非常感谢任何反馈。

2 个答案:

答案 0 :(得分:3)

一个好的经验法则是,如果满足以下任何条件,您需要锁定:

  • 如果要在多个线程上修改对象的任何字段
  • 如果任何修改涉及访问多个字段
  • 如果任何可修改字段是Double,Decimal或结构化值类型
  • 如果任何修改涉及读取 - 修改 - 写入(即添加到字段或使用另一个字段设置一个字段)

然后你可能需要锁定访问这些字段的每个方法或属性。

编辑:请记住,锁定类内部的内容很少 - 您需要做的是确保在整个的范围内不会出错逻辑运算

正如@Bevan指出的那样,如果调用代码需要多次访问一个对象,那么客户端代码应该在整个工作期间对该对象取出自己的锁,以确保另一个线程不会“在“它的访问和弄乱它的逻辑之间。”

如果需要同时取出多重锁,您还需要注意,它们始终以相同的顺序 。如果线程1在实例A上有一个锁并试图锁定实例B,并且线程2在实例B上有一个锁并试图在实例A上获得一个锁,则两个线程都被卡住而无法继续 - 你有一个死锁。

答案 1 :(得分:2)

只有使用锁定各个方法,才能使对象线程安全。你最终做的就是序列化(减慢)对象的访问。

考虑这个小例子:

var myObject = ...
var myThreadSafeList = ...
if (!myThreadSafeList.Contains(myObject))
{
    myThreadSafeList.Add(myObject);
}

即使myThreadSafeList锁定了每个方法,这也不是线程安全的,因为另一个线程可以在<{1}}和Contains()的调用之间改变列表的内容。 / p>

如果是此列表,则需要其他方法:Add()

AddIfMissing()

只有将逻辑移动到对象中,才能使用锁定操作并使其安全。

如果没有进一步的细节,很难再发表评论,但我建议如下:

  • 将所有属性设为只读,并允许任何人随时阅读
  • 提供mutator方法,这些方法包含一起修改的属性集,并在锁中以原子方式进行更改

举例说明:

var myObject = ...
var myThreadSafeList = ...
myThreadSafeList.AddIfMissing(myObject);