0

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

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

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 中运行的。

4

1 回答 1

5

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

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

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

  • 如果某些获取锁的代码假定在持有锁时集合不会更改,但随后在持有锁时调用了一些外部方法,那么尽管持有锁,外部方法可能会更改对象。

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

于 2013-11-13T19:41:15.013 回答