如何通过缓存键锁定?

时间:2012-05-23 06:46:26

标签: c# asp.net caching locking thread-safety

我正在尝试实现一个通用的线程安全的Cache方法,我想知道如何在其中实现锁定。

看起来应该是这样的:

//private static readonly lockObject = new Object();

public T GetCache<T>(string key, Func<T> valueFactory...)
{

  // try to pull from cache here

  lock (lockObject) // I don't want to use static object lock here because then every time a lock is performed, all cached objects in my site have to wait, regarding of the cache key.
  {
    // cache was empty before we got the lock, check again inside the lock

    // cache is still empty, so retreive the value here

    // store the value in the cache here
  }

  // return the cached value here

}

3 个答案:

答案 0 :(得分:4)

第一个答案

这是您使用mutex的情况 Mutex 可以使用密钥锁定以锁定该密钥 - 但您无法更改相同的资源!

public T GetCache<T>(string key, Func<T> valueFactory...) 
{
    // note here that I use the key as the name of the mutex
    // also here you need to check that the key have no invalid charater
    //   to used as mutex name.
    var mut = new Mutex(true, key);

    try
    {   
        // Wait until it is safe to enter.
        mut.WaitOne();

        // here you create your cache
    }
    finally
    {
        // Release the Mutex.
        mut.ReleaseMutex();
    }   
}

什么样的锁

我们有两个锁定案例。

1)一种情况是我们在所有池中使用公共资源,所有线程。公共资源可以是文件,也可以是数据库本身。

在常见资源中,我们需要使用互斥

2)第二种情况是当我们使用仅对池内部可见的变量时 - 不同的池无法看到该资源。例如,静态列表&lt;&gt; ,静态字典等。此静态变量,数组只能在池内访问,并且它们在不同池中不同。

在第二种情况下, lock()是最简单和最常用的使用方式。

比锁定更快

现在,当我们有一个静态字典,我们长时间保留并在那里进行过多的读/写操作时,更快的方法是避免整个程序等待,ReaderWriterLockSlim

您可以从此处获取完整示例:ReaderWriterLockSlim

使用ReaderWriterLockSlim,我们可以在不需要时避免锁定 - 我们不需要在读取时锁定静态值 - 只有在我们写入它们时。所以我可以建议我们将它们用作缓存的静态值。

asp.net中的池是什么。

映像,好像运行的不同程序相互隔离但服务于来自用户的传入请求。每个游泳池都有自己的世界,他们没有相互沟通。每个池都有初始化,静态值和生命。要在池之间拥有一些公共资源,您需要一些其他第三个程序,如数据库,如磁盘上的文件,如服务。

因此,如果您有许多池(Web园)将它们与公共资源同步,则需要使用互斥锁。要在内部同步它们,请使用锁定。

IIS app pools, worker processes, app domains
Lifetime of ASP.NET Static Variable

答案 1 :(得分:1)

我刚刚找到了LazyCache lib。我还没有在生产中试过它。

IAppCache cache = new CachingService();
ComplexObject cachedResults = cache.GetOrAdd("uniqueKey", 
    () => methodThatTakesTimeOrResources());

答案 2 :(得分:0)

.NET ConcurrentDictionary<TKey, TItem>通过为每个密钥哈希创建单独的锁来实现内部。这样做的好处是只锁定一个相关的哈希值,即使在处理项目添加和删除时也是如此。