仅限具体答案!我非常熟悉围绕集合锁定,线程安全等方面的更好(最佳)实践。只想在这个特定场景中找到一些答案/想法。
我们有一些类型的遗留代码:
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中运行。
答案 0 :(得分:5)
我可以想象在你发布的代码之外发生了三个问题:
有人可能会在没有锁定的情况下访问字典。在对象上使用lock
将阻止其他任何人同时在同一对象上使用lock
,但它不会做任何事情来防止其他线程在没有锁定的情况下使用该对象。请注意,因为编写Dictionary
[并且就此而言List
]以允许多个读者和一个仅添加信息的编写者安全地同时使用这样的方式并不困难,有些人可能会认为读取方法不需要锁定。不幸的是,这种假设是错误的:微软本可以相当便宜地增加这种线程安全性,但事实并非如此。
正如Servy建议的那样,有人可能会假设在两个独立方法的调用之间集合不会改变。
如果获取锁的某些代码假设集合在保持锁定时不会改变,但是在持有锁的同时调用了一些外部方法,则外部方法可能会改变对象正在举行锁定。
除非拥有字典的对象保留对自身的所有引用,以便外部代码没有得到对字典的引用,我认为这些问题中的第一个可能是最有可能的。然而,有时也会出现另外两个问题。