[英]Will code produce a race condition?
我有一个带有所有资源基本路径的文件。 例如:
build/scripts/script1.js
build/scripts/script2.js
我当然需要一个基本路径,例如:
https://example.org/SuperDuperSite/build/scripts/script1.js
我希望做的是在启动时使用路径将文件加载到全局字典中。 该字典仅需加载一次。 不幸的是,据我所知,基本路径直到第一个请求才可用。 所以在asp.net中,我必须使用application_beginrequest
而不是application_start
。 不好的是,现在我必须处理多线程问题。
这迫使我编写以下类型的代码:
lock(_lock) {
if (_dictionary == null) {
LoadDictionary();
}
}
当我只真正需要加载一次时,将为每个请求调用此方法。 我当然不喜欢这样。 由于性能原因,我不想锁定每个请求。 与大学讨论后,我们提出了一种解决方案:
if (_dictionary == null)
{
lock(_lock) {
if (_dictionary == null) {
LoadDictionary();
}
}
}
因此,使用该解决方案,我不需要在每个请求上都进行锁定,但是如果多个线程最终在启动时获得了本节的内容,那么我将通过再次检查该对象是否在该锁内来保护它,从而对其进行保护。 这段代码会起作用吗,还是我会遇到竞争状况?
使用双重检查的锁时要小心。
是的,它是线程安全的,但是在您的特定代码中,您可能会遇到一个细微的错误,其中_dictionary
已由另一个线程实例化 (通过了null
检查),但尚未完全填充 ,因此您可能最终尝试访问a部分填充的字典。 最后是以下两个之一:
ConcurrentDictionary
(它还带有性能影响),否则您可能会同时对字典进行读写操作,并导致死锁(是的,众所周知, Dictionary
类会在许多代码中导致死锁)。 在LoadDictionary()
末尾将bool _dictionaryLoaded
标志(仔细检查)翻转为true
可能更好。
或者,如果您在.NET 4上,请使用Lazy <> 。它更加LoadDictionary
,您所要做的就是将LoadDictionary
传递为init函数。
编辑:Lazy <>在内部使用双重检查后的lock实现 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.