【问题标题】:In what use cases is locking on ASP.NET cache required/desirable在哪些用例中需要/需要锁定 ASP.NET 缓存
【发布时间】:2015-08-24 14:15:14
【问题描述】:

在缓存中插入和检索项目时。对缓存执行锁定是最佳实践吗?我已遵循以下帖子中的指南。

What is the best way to lock cache in asp.net?

但我很想了解我是否需要锁定。这是我使用此缓存的唯一位置。

private static object _tcsLock = new object();

public TcsService()
{

}


public LiveScoreTcs GetScoreCard()
{

    // try to pull from cache here
    var scorecard = HttpContext.Current.Cache[Global.Caching.SecondXILiveScoreKey];
    if (scorecard != null)
    {
        return (LiveScoreTcs)scorecard;
    }

    lock (_tcsLock)
    {
        // cache was empty before we got the lock, check again inside the lock
        scorecard = HttpContext.Current.Cache[Global.Caching.SecondXILiveScoreKey];
        // cache is still empty, so retreive the value here
        if (scorecard == null)
        {
            scorecard = BuildSecondXiLiveScorecard();
            // store the value in the cache here
            if (scorecard != null)
            {
                HttpContext.Current.Cache.Insert(Global.Caching.SecondXILiveScoreKey, scorecard,
                null,
                Global.Caching.AbsoluteExpiration.Tcs,
                Cache.NoSlidingExpiration,
                CacheItemPriority.Default,
                null);
            }
        }

    }

    // return the cached value here
    return (LiveScoreTcs)scorecard;
}

【问题讨论】:

  • _tcsLock 在哪里声明和/或初始化?
  • 刚刚更新..谢谢
  • 请注意Cache 在多线程环境中会出现任何共享状态的所有正常问题。最重要的是,可能有一些特定于Cache 的问题,但“用例是什么”的答案是“所有正常用例,可能还有一些Cache 特定用例”。

标签: c# asp.net caching


【解决方案1】:

锁定与您在代码中的哪个位置使用它无关,而是是否有多个线程可以在任何时候执行该代码。如果有可能出现竞争条件,您需要锁定,即使显然在开发中并且您的特定设置没有出现错误。之所以如此,是因为多线程受到许多因素的影响,以至于您无法预测其行为。

因此,如果这是一个多线程应用程序(Web 服务器),您需要锁定。

减少锁定的代码量也是一个不错的建议,因为冲突会将线程置于等待状态,您希望让它们尽可能少地等待。

如果你认为你有很多读访问和很少写访问,你可能想研究更复杂的机制,比如 Semaphore 并采用 Multiple Reader Single Writer 模式。

真的,这完全取决于您在应用程序的其余部分(线程或并行 Web 请求)中执行的操作。

【讨论】:

  • 这根本没有解决问题中的具体情况。
  • @Servy:视情况而定。如果问题是代码,那么它会解决它。如果问题是帖子中的文字,那么可能不是。当他需要锁定他放入缓存的对象时,OP 认为他需要“锁定缓存”。
  • @JohnSaunders 这个答案只是一般性地谈论锁定,它绝不特定于 OP 实际询问的情况。我的意思是,他一开始就说它只有在有多个线程时才相关,但我们知道它是一个 ASP 应用程序,我们知道代码可以由多个线程同时运行,并且我们知道锁不需要遵循读取器/写入器模式,并且它无法解释为什么锁存在,以及它不存在的后果是什么。
  • @Servy:请参阅我对问题的评论。我希望 OP 会用它来澄清他的问题。
  • @Servy 我同意。您对我的回答的描述是正确的。但是当他询问“关于我是否需要锁定的一些上下文”时,我看到的是他在没有理解更大的图景的情况下复制了代码。他问的是WHY而不是HOW(他已经解决了)。我特意给出了关于锁定的一般情况。
【解决方案2】:

如果您不使用lock,那么您有可能最终重新创建要多次缓存的对象。在某些情况下,这是一个主要问题,特别是如果做这项工作会导致副作用,而这对不执行多次很重要,并且在某些情况下,多次做这项工作会浪费一点时间,而且性能有点低,这可能或可能不是您需要避免的。

因此,是否可以确保BuildSecondXiLiveScorecard 在从缓存中过期之前永远不会执行多次,这是我们不能说的,但这是没有锁定的唯一潜在问题。

【讨论】:

  • 另一种可能出现问题的情况是,如果真的只有一个scorecard 实例供所有线程使用。即使创建它们很便宜,您也可能不希望线程 1 使用一个实例而线程 2 使用另一个实例。代码可能依赖于只有一个实例。
  • @JohnSaunders 是的,但是由于缓存可能会过期并需要重新创建对象,因此在这两种情况下您实际上都无法依赖它。
  • 你会 - 如果你锁定将有零个或一个实例。不可能有两个实例。
  • @JohnSaunders 直到它从缓存中过期,此时可能有一个对象仍在使用它之前从缓存中获取的旧对象,以及另一个创建新实例的对象,因为缓存是空的。如果缓存永远不会使对象过期,它只会是一个单例。
  • 是的,好点。当对象从缓存中过期时,可能需要对其进行清理。例如,如果缓存中的对象持有数据库连接或其他实现IDisposable的东西。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-27
相关资源
最近更新 更多