【问题标题】:Multiple lock objects necessary?需要多个锁对象吗?
【发布时间】:2013-02-11 14:13:35
【问题描述】:

给定以下类:

class x
{
    Object lockOne = new Object();
    Object lockTwo = new Object();

    List<Something> listOne = new List<Something>();
    List<Something> listTwo = new List<Something>();

    void MethodOne()
    {
        lock(lockOne)
        {
            // some operation on listOne
        }
    }

    void MethodTwo()
    {
        lock(lockTwo)
        {
            // some operation on listTwo
        }
    }
}

假设MethodOne()MethodTwo() 可以从不同的线程同时调用,那么使用两个锁定对象是否正确,注意listOnelistTwo 无论如何都不相关。锁涉及的唯一操作是上面的 cmets 中指定的操作。

【问题讨论】:

  • 这称为锁拆分,如果两个对象和方法是独立的,这是减少争用的好方法。
  • 这应该叫常识,反其道而行之是非常不好的做法。
  • 您可能想要查看的一件事是使用ReaderWriterLock。如果您只从列表中读取它允许多个线程一次使用它(List 具有线程安全读取),一旦您需要写入,您升级锁,然后只有一个线程可以写入并且所有读取器都被阻止,之后多个阅读器可以重新开始。

标签: c# multithreading concurrency locking


【解决方案1】:

是的,没错。它避免了仅仅因为正在处理另一个列表而不必要地锁定一个列表。

【讨论】:

  • 对吗?是的。浪费?同样是的,这里不需要单独的锁对象。
  • 为了澄清 svick 所说的,他并不是说要锁定单个锁定对象,而是 not to use any lock objects at all 并锁定列表本身。
【解决方案2】:

这里不需要单独的锁对象。以下代码也可以正常工作,代码更少,开销更少,错误使用错误锁的机会更少:

class x
{
    List<Something> listOne = new List<Something>();
    List<Something> listTwo = new List<Something>();

    void MethodOne()
    {
        lock (listOne)
        {
            // some operation on listOne
        }
    }

    void MethodTwo()
    {
        lock (listTwo)
        {
            // some operation on listTwo
        }
    }
}

【讨论】:

  • 就像一个注释,最佳实践(像这样显示)是只锁定 private 到类的项目 - 否则你不知道什么外部代码可能会尝试锁定它何时并导致死锁或竞争条件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-08
  • 2021-09-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多