【问题标题】:Should my lock object be static when used to update static properties [duplicate]当用于更新静态属性时,我的锁对象是否应该是静态的?
【发布时间】:2021-09-17 22:48:56
【问题描述】:

我有一个具有静态属性的非静态类。静态属性是一个字典,它是在第一次需要时构建的。

所以使用字典的代码看起来像这样:

// Ensure dictionary is built
if (MyDictionary == null)
{
    lock (LockObject)
    {
        if (MyDictionary == null)
        {
            MyDictionary = new();
            BuildDictionary(MyDictionary);
        }
    }
}

我不清楚LockObject 是否应该是静态的。

我倾向于它不是静态的,但我在网上找到的一些信息似乎表明它应该是。

如果锁对象是静态的,那是不是意味着同一个类的其他实例不会被阻塞?

【问题讨论】:

  • 锁定对象也应该是静态的。否则每个实例都将使用自己的锁对象,因此不会阻塞其他实例。顺便说一句,为什么不使用Lazy<T>
  • @Dimitry:我在想只要锁定对象是不同的实例,其他代码就会被阻止。我希望我能找到一篇关于这方面的好文章。微软的文档似乎缺乏。我可以看看 Lazy 但是,在这里,BuildDictionary() 实际上是一个在派生类中被覆盖的抽象方法,我不确定Lazy<> 不会使事情复杂化。
  • 这只是对@dimitry 对Lazy<T> 的建议的+1。单例初始化错误的方法有很多;使用 Lazy 意味着您不必考虑它们。我发现它简化了我的代码。不过,您可能仍然希望对字典的访问进行静态锁定。
  • 如果你这样做(你不应该这样做,你应该使用LazyLazyWithNoExceptionCaching)然后分配给MyDictionary填充一个临时字典不是first。原样的代码有时会导致一些调用者看到一个空字典(或者更糟糕的是,因为他们正在从字典中读取而另一个线程正在写入它,所以会出现异常)。
  • If the lock object is static, wouldn't that mean other instances of the same class would not be blocked? 你为什么这么认为?想想这样的锁——它是一根会说话的棍子。没有说话棒你就不能说话。如果你只想要一个人说话,你想要几根棍子? 1个,还是每人1个?显然只有 1。因此 - static 是您所需要的。

标签: c# multithreading locking


【解决方案1】:

我不清楚的是 LockObject 是否应该是静态的?

这个特定问题没有正确或错误的答案,这取决于你想做什么。

一般来说

如果您要保护的对象是static,则使用static 锁定它。

并且,对于需要锁定的类实例中的对象,不要使用static

例如:

class Thing
{
    /// Global objects
    static object _lockPublicDictionary;
    static SortedDictionary<int, string> PublicDictionary;

    /// Per instantiation objects
    object _lockPrivateDictionary;
    SortedDictionary<int, string> PrivateDictionary;
}

如果出于某种原因您想为该类的所有实例全局锁定该类的对象,那么您可以使用静态锁。

static object _masterLock
SpecialObject Special;

我想不出一个用例,也许是某种同步对象,所有实例都知道彼此,一个实例可以通过一些反向通道与其他实例通信.

另外,我建议查看Singleton Pattern,它只会生成一个类的实例。它类似于static class,根据您的问题,它可能就是您真正想要的。

【讨论】:

  • 严格来说,在“lock granularity 使用什么”的 3 个答案中 - 锁比数据块多”、“每个数据块一个锁”、“锁比数据块少”,肯定有一个错误的答案 - 比数据更多的锁(这是 OP 建议的选项)......这是单个锁对象的用例 - 当你只有一个可能更重要的锁对象时,不可能陷入死锁而不是一些潜在的锁定争用。
  • “对此没有正确或错误的答案” - 是的,有。所有试图进入被锁定区域的代码都必须使用相同的lock 对象,如果它们正在访问相同的数据。
  • @Enigmativity 当然。但这不是操作员所要求的:-)
猜你喜欢
  • 2017-03-19
  • 1970-01-01
  • 2014-05-24
  • 1970-01-01
  • 1970-01-01
  • 2012-03-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-11
相关资源
最近更新 更多