C#与多线程共享锁

时间:2009-12-11 14:11:41

标签: c# multithreading synchronization locking

在同一组数据上运行的不同对象之间是否存在“共享”锁定的常用方法?

我知道通常不建议使用公共对象进行锁定。

例如,Queue可以实现为线程安全,但是其他一些类可能需要特定的锁才能锁定多个Queue操作。如果我有第三个类,还需要在同一个Queue实例上进行多次锁定操作,会发生什么?

例如: (假设L<T>是一个线程安全的列表,只是为了节省一些打字)

class Worker
{
    private readonly L<Something> _list;
    public Worker(L<Something> list) { _list = list; }

    private readonly object _lock = new object();
    public void Replace(Something old, Something new)
    {
       lock (_lock) 
       {
          if (_list.Contains(old))
          {
              _list.Remove(old);
              _list.Add(new);
          }
       }
    }
}

如果某个其他类在另一个线程上删除了old条件之后的if元素,则列表将不再包含该元素,因为_lock是一个私有对象。

我应该锁定实际的列表实例吗?

3 个答案:

答案 0 :(得分:10)

不要将此列表公开为属性,只显示与其交互的方法。然后,您可以处理一个类中的所有锁定,而不处理公共锁定对象。

答案 1 :(得分:9)

常见的方法是公开ICollection.SyncRoot等属性。当然,每个人必须服从锁才能使其发挥作用。

如果您可以避免这种情况,并将操作封装为ck建议,那将更加强大且易于理解。

答案 2 :(得分:5)

从技术上讲,您可以轻松地公开锁定对象。这样做的问题是建议不将它们公开的真正原因是僵局。

如果锁定对象被暴露,则会引入一些其他代码将锁定此对象而不考虑锁定顺序的风险。这反过来会导致死锁。

即使没有明确暴露锁,也存在同样的危险。

最好的方法是不要公开锁 - 既不是隐式也不是显式。换句话说,将它们完全埋在提供服务的课程中。不幸的是,有时这不是一个选择。

相关问题