我知道这个话题受到了冲击,因为我已经阅读过关于SO以及其他地方的数以万计的帖子,但我还没有找到明确的答案,所以如果你被这种看似冗余所感染,我会道歉。
我的情况是有一次写入,读取数百万资源。创建资源非常昂贵,并且写锁定的争用也可能非常高。此外,我无法预测这将运行什么处理器,因此我不知道内存模型将在底下。我正在编译在.NET 3.5,.NET 4.0和Mono 2.10中构建的3个版本的程序集。
由于资源的高争用,我需要尽可能高效,并且希望使用无锁模式,至少对于读取。我理解用于创建资源的双锁检查模式,但是由于_resource在内存屏障之外的访问,它是否有效(在所有处理器上)存在分歧。我是否需要在_resource字段上使用volatile? ReaderWriterLockSlim更适合这种情况吗?我应该问其他什么问题?
if(_resource == null)
{
lock(_locker)
{
if(_resource == null)
{
//create resource here...
}
}
}
此外,还有其中一些:
if(_resource == null)
{
return _resourceDefault;
}
return _resource.GetSomething();
答案 0 :(得分:1)
决定将我的评论推广到答案。
创建单身人士的阅读时,http://msdn.microsoft.com/en-us/library/ff650316.aspx。它交叉链接了一篇文章,深入解释了与双重检查锁定相关的一些问题。为了完全安全,微软文章推荐使用volatile。
如果您真正想要的只是创建一个单身人士(一次性事情......没有锁定促销或任何必要的东西),读者作家锁并没有真正为您买任何东西。您真的只需要保护资源的创建)。创建资源后,您根本不会触摸锁定。
我会设计对你的单身人士的访问,以便总是通过静态属性/方法,这样你就可以随时进行双重检查。
关于资源默认情况,我认为我对您的情况了解不够正确。您是否期望主资源永远为空(除非在创建之前)?根据您的使用情况,您可以使用非阻塞的Moniter.TryEnter并返回一个值,以便在收到锁定时通知您。如果您无法立即获得锁定来创建单例,则可以返回默认值。