【问题标题】:C# sharing locks with multithreadingC# 多线程共享锁
【发布时间】:2010-12-25 16:33:09
【问题描述】:

是否有一种通用的方法可以在对同一组数据进行操作的不同对象之间“共享”锁?

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

例如,队列可以实现为线程安全的,但其他一些类可能需要特定的锁才能锁定多个队列操作。如果我有第三个类,它也需要对同一个 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);
          }
       }
    }
}

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

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

【问题讨论】:

    标签: c# multithreading synchronization locking


    【解决方案1】:

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

    【讨论】:

    • 我明白你的意思,但在这种情况下,与该数据交互的所有方法都必须属于同一个类。你不能有一个不同的类来执行一系列操作,并且也是线程安全的。
    • @Groo re:Robert Grant - 没关系,他是个本地傻瓜。
    • 另外我相信你必须有 2000 个代表。
    【解决方案2】:

    一种常见的方法是公开一个属性,例如ICollection.SyncRoot。当然,每个人都必须遵守锁才能使其工作。

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

    【讨论】:

    • 谢谢,这是我问题的正确答案:共享锁的常用方法。我知道其中的含义,但只是想看看是否存在我不知道的第三种可能性。
    【解决方案3】:

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多