一次写入,多次读取锁定 [英] Write-Once, Read-Many Lock

查看:142
本文介绍了一次写入,多次读取锁定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道这个话题已经引起了很大的反响,因为我在SO上以及其他地方都阅读了数以百万计的帖子,但是我还没有找到确切的答案,因此,如果您因这种看似多余的内容而感到生气,我深表歉意.

I know this topic has been pounded as I have read gillions of posts on SO as well as elsewhere about it, but I have yet to find a definitive answer, so my apologies if you are offended by this seeming redundancy.

我遇到的情况是存在一次写入,读取数百万个资源.创建资源非常昂贵,并且写锁上的争用也可能很高.此外,我无法预测它将在哪个处理器上运行,因此我不知道其下面的内存模型.我正在编译在.NET 3.5,.NET 4.0和Mono 2.10中构建的程序集的3个版本.

I have a situation where there is a write-once, read-millions resource. The resource is extremely expensive to create and the contention on the write-lock could be very high as well. Furthermore, I cannot predict what processor this will be run on and so I do not know what the memory-model will be underneath. I am compiling 3 versions of the assembly built in .NET 3.5, .NET 4.0, and Mono 2.10.

由于资源的争用很大,因此我需要使其尽可能高效,并且希望至少在读取时使用无锁模式.我了解用于创建资源的双锁检查模式,但是由于在内存屏障之外访问_resource,因此对于(是否在所有处理器上)工作是否有效一直存在分歧.我需要在_resource字段上使用volatile吗? ReaderWriterLockSlim是否更适合这种情况?我还要问什么其他问题?

Because of the high-contention for the resource, I need to make this as efficient as possible and would like to use a lock-free pattern, at least for the reads. I understand the double lock check pattern for creating the resource, but there has been disagreement over whether or not it works (on all processors) due to the access of _resource outside the memory barrier. Do I need to use volatile on the _resource field? Is a ReaderWriterLockSlim a better fit for this scenario? What other questions should I be asking?

if(_resource == null)
{
    lock(_locker)
    {
        if(_resource == null)
        {
            //create resource here...
        }      
    }
}

此外,其中会有很多:

if(_resource == null)
{
    return _resourceDefault;
}

return _resource.GetSomething();

推荐答案

决定将我的评论升级为答案.

Decided to promote my comment to an answer.

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

On creating singleton's read, http://msdn.microsoft.com/en-us/library/ff650316.aspx . It cross links a paper that goes in depth explaining some of the problems related to double checked locking. To be completely safe the microsoft article does recommend the volatile.

如果您真正想要的只是创建一个单例,那么读者写锁实际上并不会为您买任何东西(一次性的东西……不需要锁升级或任何其他操作.您实际上只需要保护资源的创建即可) ).一旦创建资源,您将根本不会碰锁.

A reader writer lock doesn't really buy you anything if all you really just want is to create a singleton (one time thing... no lock promotion or anything is necessary. You really just need to protect creation of the resource). Once the resource is created you won't be touching the lock at all.

我会设计对您的单例的访问,使其始终通过静态属性/方法,以便您始终可以进行仔​​细检查.

I would design access to your singleton to always go through a static property/method so you can always do the double check.

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

About the resource default, I don't think I know enough about your situation to answer properly. Do you expect the primary resource to ever be null (except before it was created)? Depending on your use case, you might be able to use a Moniter.TryEnter which is nonblocking and returns a value letting you know if you received the lock. If you were not able to immediately get the lock to create the singleton, you could return your default.

这篇关于一次写入,多次读取锁定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆