我有一个文件,其中包含我所有资源的基本路径。例如:
https://example.org/SuperDuperSite/build/scripts/script1.js
我当然需要一个基本路径,例如:
application_beginrequest
我希望做的是在启动时使用路径将文件加载到全局字典中。字典只需要加载一次。不幸的是,据我所知,基本路径在第一次请求之前是不可用的。所以在asp.net中我必须使用application_start
而不是 lock(_lock) {
if (_dictionary == null) {
LoadDictionary();
}
}
。现在我不得不处理多线程问题。
迫使我编写以下类型的代码:
if (_dictionary == null)
{
lock(_lock) {
if (_dictionary == null) {
LoadDictionary();
}
}
}
当我只需要加载一次时,会为每个请求调用此方法。当然,我真的不喜欢这样。出于性能原因,我不想锁定每一个请求。在与我们提出的大学交谈之后,有一个解决方案:
static String encryptionKey = "0123456789123456";
因此,使用此解决方案,我不需要锁定每个请求,但如果多个线程最终在启动时获取此部分,我将通过检查该对象是否在锁内再次为空来保护它。这段代码会起作用还是我会遇到竞争条件?
答案 0 :(得分:1)
使用双重检查锁时要小心。
是的,它是线程安全的,但在您的特定代码中,您可能遇到一个微妙的错误,其中_dictionary
已被实例化另一个线程(通过null
检查),但尚未完全填充,您最终可能会尝试访问部分填充的字典。最后得到这两个中的一个:
ConcurrentDictionary
(这也会影响其性能),否则您可能会同时读写字典并导致死锁(是的,Dictionary
已知class会在许多代码中导致死锁。)在bool _dictionaryLoaded
结尾处翻转到true
的{{1}}标记(经过双重检查)可能更好。
如果您使用的是.NET 4,请使用Lazy<>。它更清晰,您只需传入LoadDictionary()
作为初始化函数即可。
编辑:懒惰&lt;&gt;是internally implemented with a double-checked lock。