【问题标题】:Lock ConcurrentDictionary while removing and adding multiple items?在删除和添加多个项目时锁定 ConcurrentDictionary?
【发布时间】:2015-07-07 19:29:41
【问题描述】:

我在 StackOverflow 上阅读了以下文章:ConcurrentBag - Add Multiple Items?Concurrent Dictionary Correct Usage,但答案对我来说仍然不明显。

我有这种情况:我在数据库中有Leaderboard 表,我会定期更新它。为了优化服务器,我缓存了结果,所以我使用了 ConcurrentDictionary(因为有不同类型的排行榜,例如 All-time、3-days、7-days 等...)。

这是我在更新排行榜上的代码:

        var leaderboards = business.UpdateLeaderboard(LeaderboardUpdater.LeaderboardDaySpans, LeaderboardUpdater.LeaderboardCount);
        this.LastUpdateTime = now;

        // The LeaderboardCache is ConcurrentDictionary<int, LeaderboardResponseViewModel>
        this.LeaderboardCache.Clear();
        foreach (var leaderboard in leaderboards)
        {
            this.LeaderboardCache.TryAdd(leaderboard.DaySpan, new LeaderboardResponseViewModel(leaderboard));
        }

假设用户可以随时请求排行榜信息。所以我有一些问题:

  • 我是否应该使用Concat 而不是foreach 来确保同时添加所有项目?
  • 即使我使用Concat,如何确保用户不会在ClearConcat方法中间请求?
  • 我应该应用额外的锁吗?如果是这样,我如何确保并发读取,因为同时多个读取是可以的?

【问题讨论】:

    标签: c# .net multithreading concurrency concurrentdictionary


    【解决方案1】:

    您在错误的级别管理并发。显然,您希望以原子方式处理字典内容,但您在项目级别同步(不成功)。

    使用如下数据结构:

    volatile Lazy<...> myCache = new Lazy<Dictionary<...>>(ProduceCacheValues);
    

    当你想刷新缓存值时,创建一个新的Lazy 并覆盖myCache

    或者,只需使用锁。对于低频的短时操作,这通常已经足够了。

    澄清一下,没有办法在ConcurrentDictionary atomic 中创建多个项目或操作。

    【讨论】:

    • 谢谢,我学到了 2 个新东西:volatileLazy。但我需要问 2 个问题:1. 我是否仍应使用 ConcurrentDictionary 而不是您的示例中的普通 Dictionary? 2、内联函数ProduceCacheValues使用leaderboards变量,即EntityFramework实体,Context可能在延迟加载的时候就已经被释放了?
    • 你不应该改变惰性对象的内容。然后,不需要同步。我不知道 EF 的实体在处理上下文时是否会以某种方式变得无效。我通常从不将任何 EF 的东西放在全局变量中。我总是将数据复制到干净的 DTO 中。更安全。
    • 非常感谢。我只知道Dictionary 不是线程安全的,但不知道它在只读时是否是线程安全的。关于实体,我会按照你的建议去做,我首先在惰性工厂方法之外将它们复制到 DTO 中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-18
    • 1970-01-01
    • 2015-04-01
    • 2012-08-29
    • 2012-09-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多