0

我知道这个话题已经被猛烈抨击了,因为我已经阅读了关于 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();
4

1 回答 1

1

决定将我的评论推广到答案。

在创建单例阅读时, http: //msdn.microsoft.com/en-us/library/ff650316.aspx。它交叉链接了一篇深入解释与双重检查锁定相关的一些问题的论文。为了完全安全,微软的文章确实推荐了 volatile。

如果您真正想要的只是创建一个单例,那么读写器锁并不会真正为您买任何东西(一次性......没有锁升级或任何必要的东西。您真的只需要保护资源的创建)。创建资源后,您将根本不会触摸锁。

我会设计访问你的单身人士总是通过一个静态属性/方法,所以你总是可以做双重检查。

关于资源默认值,我认为我对您的情况了解不足,无法正确回答。您是否期望主要资源永远为空(创建之前除外)?根据您的用例,您可能可以使用非阻塞的 Moniter.TryEnter 并返回一个值,让您知道您是否收到了锁。如果你不能立即获得锁来创建单例,你可以返回你的默认值。

于 2012-07-16T18:12:37.887 回答