在删除和添加多个项目时锁定ConcurrentDictionary?

时间:2015-07-07 19:29:41

标签: c# .net multithreading concurrency concurrentdictionary

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

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

以下是更新排行榜的代码:

        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方法的中间请求?
  • 我应该申请额外的锁吗?如果是这样,我怎样才能确保并发读取,因为同时多次读取是可以的?

1 个答案:

答案 0 :(得分:2)

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

使用以下数据结构:

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

如果要刷新缓存值,请创建新的Lazy并覆盖myCache

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

为了澄清,没有办法在ConcurrentDictionary原子中制作多个项目或操作。