C#与多线程共享锁

Gro*_*roo 3 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);
          }
       }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果在另一个线程上的某个其他类oldif条件之后删除该元素,则list将不再包含该元素,_lock私有对象也是如此.

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

cjk*_*cjk 10

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


Jon*_*eet 9

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

如果您可以避免这种情况,并按照ck的建议封装操作,那么这将更加健壮且易于理解.


mfe*_*old 5

从技术上讲,您可以轻松公开锁定对象。问题在于建议不公开的真正原因是僵局。

如果锁定对象暴露在外,则会带来一些其他代码将对该对象进行锁定的风险,而与锁定顺序无关。这又可能导致死锁。

即使未显式公开锁,也存在相同的危险。

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