首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C#字典与ReaderWriterLockSlim

C#字典与ReaderWriterLockSlim
EN

Stack Overflow用户
提问于 2009-08-25 19:10:03
回答 3查看 4.8K关注 0票数 2

我对多线程非常陌生,由于某种原因,这门课给我带来了比它应该有的更多的麻烦。

我正在ASP.net缓存中设置一个字典--它将经常被查询单个对象,偶尔会被枚举,并且很少被写入。我要注意的是,字典数据几乎从未改变过,我计划每天让它过期,并在它离开缓存时从数据库中进行重新构建。

我相信,只要字典没有编写,键的枚举和访问就是安全的。我认为基于ReaderWriterLockSlim的包装类是可行的,但我在几点上不太清楚。

如果我使用Lock,我相信我既可以锁定令牌,也可以锁定正在保护的实际对象。我不知道如何使用ReaderWriter锁来做类似的事情。我是否正确地认为,由于ReaderWriterLocks超出了彼此的范围,包装器的多个实例将无法正确锁定?

编写这样一个包装器的最佳实践是什么?将其构建为静态对象似乎是多余的,因为主要对象是由缓存维护的。Singleton的观点似乎受到了反对,我对上面提到的针对单个实例的范围问题表示关注。

我已经看到了一些类似包装器的实现,但我无法回答这些问题。我只想确保我对自己正在做的事情有一个坚定的把握,而不是剪和粘贴我的方式。非常感谢您的帮助!

**编辑:希望这是一个更清晰的总结,我想找出-*

1.我是否正确地认为锁不影响基础数据,并且像任何其他变量一样限定作用域?

举个例子,我有以下几点-

代码语言:javascript
复制
MyWrapperClass 
{
    ReaderWriterLockSlim lck = new ReaderWriterLockSlim();
    Do stuff with this lock on the underlying cached dictionary object...
}

MyWrapperClass wrapA = new MyWrapperClass();
MyWrapperClass wrapB = new MyWrapperClass();

我认为wrapA锁和wrapB锁不会交互,如果wrapA & wrapB都尝试操作,那么这是不安全的,对吗?

如果是这样的话,“共享”锁数据的最佳实践方法是什么呢?

这是一个Asp.net应用程序-将有多个页面需要访问数据,这就是为什么我要这样做的第一。确保不同包装程序使用相同锁的最佳实践是什么?我的包装器是否应该是所有线程都在使用的静态或单例,如果不是的话,更优雅的选择是什么?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2009-08-26 18:17:46

缓存中有多个字典对象,并且希望每个对象独立锁定。“最好”的方法就是使用一个简单的类来完成它。

代码语言:javascript
复制
public class ReadWriteDictionary<K,V>
{
    private readonly Dictionary<K,V> dict = new Dictionary<K,V>();
    private readonly ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim();

    public V Get(K key)
    {
        return ReadLock(() => dict[key]);
    }

    public void Set(K key, V value)
    {
        WriteLock(() => dict.Add(key, value));
    }

    public IEnumerable<KeyValuePair<K, V>> GetPairs()
    {
        return ReadLock(() => dict.ToList());
    }

    private V2 ReadLock<V2>(Func<V2> func)
    {
        rwLock.EnterReadLock();
        try
        {
            return func();
        }
        finally
        {
            rwLock.ExitReadLock();
        }
    }

    private void WriteLock(Action action)
    {
        rwLock.EnterWriteLock();
        try
        {
            action();
        }
        finally
        {
            rwLock.ExitWriteLock();
        }
    }
}

Cache["somekey"] = new ReadWriteDictionary<string,int>();

MSDN上的ReaderWriterLockSlim的帮助页面上还有一个更完整的例子。要使它成为通用的并不难。

编辑来回答你的新问题-

1.)您是正确的,wrapA和wrapB不会交互。它们都有自己的ReaderWriterLockSlim实例。

2.)如果您需要所有包装类之间的共享锁,那么它必须是静态的。

票数 8
EN

Stack Overflow用户

发布于 2013-03-07 15:56:48

ConcurrentDictionary做你想做的一切,然后做一些。部分System.Concurrent.Collections

票数 3
EN

Stack Overflow用户

发布于 2009-08-25 19:28:22

锁定的标准方法是:object lck = new object(); ... lock(lck) { ... },在这个实例中,对象lck表示锁。

ReadWriterLockSlim没有太大的不同,只是在本例中,实际的ReadWriterLockSlim类代表实际的锁,所以无论您在哪里使用lck,现在都使用ReadWriterLockSlim。

代码语言:javascript
复制
ReadWriterLockSlim lck = new ReadWriterLockSlim();

...

lck.EnterReadLock();
try
{
    ...
}
finally
{
    lck.ExitReadLock();
}
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1330352

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档