我已经在StackOverflow上阅读了以下文章:
ConcurrentBag – Add Multiple Items?和
Concurrent Dictionary Correct Usage,但答案对我来说仍然不明显.
我有这种情况:我在数据库中有Leaderboard表,我会定期更新它.为了优化服务器,我缓存了结果,所以我使用ConcurrentDictionary(因为有不同类型的排行榜,例如All-time,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,如何确保用户不会在Clear和Concat方法的中间请求?
>我应该申请额外的锁吗?如果是这样,我怎样才能确保并发读取,因为同时多次读取是可以的?
最佳答案 您正在以错误的级别管理并发性.显然,您希望以原子方式处理字典内容,但是您在项目级别进行同步(未成功).
使用以下数据结构:
volatile Lazy<...> myCache = new Lazy<Dictionary<...>>(ProduceCacheValues);
当您想刷新缓存值时,创建一个新的Lazy并覆盖myCache.
或者,只需使用锁.对于通常足够好的低频短时操作.
为了澄清,没有办法在ConcurrentDictionary原子中创建多个项目或操作.