在 asp.net mvc 应用程序中缓存时我们真的需要锁定吗?

Do we really need locking when are caching in asp.net mvc application?

我看到很多缓存示例,其中包括 locking.I 我正在尝试为整个 application.Do 缓存公共列表 我真的需要像下面这样使用锁吗?如果我不使用锁定,可能发生的最糟糕的事情是 ;

如果多个线程在大约相同的时间检测到缓存未命中 time.They 可能会尝试加载数据 simultaneously.In 结论,数据将相同...

是真的吗?

 public class Worker

{

    private static object someLock;

    public static object CacheMethod()
    {

        var results = HttpContext.Current.Cache["Common"];

        if (results == null)
        {
            lock (someLock)
            {
                results = HttpContext.Current.Cache["Common"];
                if (results == null)
                {
                    results = GetResultsFromSomewhere();
                    HttpContext.Current.Cache.Insert("Common", results, null,
                            DateTime.Now.AddHours(1), Cache.NoSlidingExpiration);
                }
            }
        }
        return results;

    }``

这叫做double-checked locking pattern。是的,如果您有很多请求并且检索数据所需的时间比请求之间的时间更长,那么您可能对同一数据有多个请求。

如果没有锁定,每个额外的线程都会接收相同的数据,因此额外线程使用的 CPU/Network Activity/RAM 的数量就被浪费了。这是否是一个问题取决于您网站的流量和可用的 server/network 资源。

但是,更重要的是确保您的 results 对象本身是线程安全的,因为可以保证有多个线程与其状态进行交互。最简单的方法就是将其所有属性设置为只读,但如果您需要可写属性,则可以将 ReaderWriterLockSlim 与确保原子操作的方法结合使用(请参阅 link 中的示例) .

此锁用于防止缓存冲压。如果缓存为空并且需要一段时间来填充,那么所有传入的请求都将开始填充缓存。根据数字的计算方式,这可能会造成灾难性的性能损失。

如果 GetResultsFromSomewhereThread.Sleep(10000) 那么这很容易发生。

该特定代码的坏处在于它是所有缓存键的一把锁。通常你需要一把钥匙一把锁。