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

本文关键字:锁定 ConcurrentDictionary 删除 添加 | 更新日期: 2023-09-27 18:01:40

我在StackOverflow上阅读了以下文章:ConcurrentBag -添加多个项目?和并发字典正确用法,但答案对我来说仍然不明显。

我有这样的场景:我在数据库中有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方法的中间请求?
  • 我应该应用一个额外的锁吗?如果是这样,我如何确保并发读取,因为多个读取在同一时间是可以的?

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

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

使用以下数据结构:

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

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

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

需要说明的是,没有办法在一个ConcurrentDictionary原子中创建多个项或操作。