【问题标题】:Generic dictionary - possible locking issue?通用字典 - 可能的锁定问题?
【发布时间】:2013-11-26 13:45:15
【问题描述】:

请仅提供具体答案!我对集合锁定、线程安全等方面的更好(最佳)实践非常熟悉。只是想要一些关于这个特定场景的答案/想法。

我们有一些类型的遗留代码:

public class GodObject
{
    private readonly Dictionary<string, string> _signals;

    //bunch of methods accessing the dictionary

    private void SampleMethod1()
    {
        lock(_signals)
        {
            //critical code section 1
        }
    }

    public void SampleMethod2()
    {
        lock(_signals)
        {
            //critical code section 2
        }
    }
}

对字典的所有访问都在这样的锁定语句中。我们遇到了一些错误,如果锁定没有显式工作,可以解释这些错误 - 这意味着 2 个或更多线程同时访问字典。

所以我的问题是 - 是否存在多个线程可以同时访问关键部分的情况?对我来说,这应该是不可能的,因为引用是只读的,所以对象似乎不会发生变化,并且 lock() 周围的大多数问题都与死锁有关,而不是没有发生同步。但也许我错过了一些细微差别或明显的东西?

这是在长期运行的 Windows 服务 .NET Framework 3.5 中运行的。

【问题讨论】:

  • 你能参考你得到的错误陈述吗?这可能有助于确定错误,或者如果您可以解释关键部分的内容。
  • 很可能一些调用者调用GodObject 的多个方法,期望它们之间没有其他方法运行,并且违反了这种期望。
  • 您还没有谈到您遇到的问题。你的问题的答案是否,Monitor.Enter 将只允许一个线程执行临界区,直到调用Monitor.Exit。这就是 lock 语句在内部所做的。
  • 请解释你遇到的问题,你提到死锁,你知道导致死锁的一系列事件吗?还有其他方法使用_signals(即使是只读访问)?现在,正如所写,您的代码不会死锁,也不会出现线程读/写问题,但是您删除了太多细节,因此我们无法告诉您问题出在哪里。
  • 您的任何方法是否会在 GodObject 类之外泄漏字典?

标签: c# .net thread-safety


【解决方案1】:

我可以想象在您发布的代码之外会出现三个问题:

  • 有人可能会访问字典而不锁定它。在对象上使用lock 将阻止其他任何人同时在同一个对象上使用lock,但它不会做任何事情来阻止其他线程在不锁定对象的情况下使用该对象。请注意,因为编写Dictionary [和就此而言List] 以允许多个读者和一个只添加信息的作者安全同时使用的方式并不会太困难,所以有些人可能会假设读取方法不需要锁定。不幸的是,这个假设是错误的:微软本可以相当便宜地添加这样的线程安全,但没有。

  • 正如 Servy 所建议的那样,有人可能会假设集合不会在调用两个独立方法之间发生变化。

  • 1234563被持有的锁。

除非拥有字典的对象保留对自身的所有引用,以使外部代码永远不会获得对字典的引用,否则我认为这些问题中的第一个可能是最有可能的。但是,有时也会出现其他两个问题。

【讨论】:

  • 感谢超级猫的回答。我只是想弄清楚是否有一些带有锁/监视器的边缘情况或一些带有泛型/字典的时髦东西可能会造成麻烦。在生产代码中,恰好有 3 种这样的方法,并且字典仅在那些锁定语句中被触及,问题不在于死锁,而在于“可能不起作用”的锁。我只是在消除“不可能” :) 。对于任何感兴趣的人,这是用于过滤 .net 文件观察器引发的多个事件的文件观察器的一部分。
猜你喜欢
  • 2010-09-29
  • 2013-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-04
  • 1970-01-01
  • 2011-08-18
  • 2011-06-01
相关资源
最近更新 更多