潜在的并发问题?
我一直在构建ASP.NET MVC应用程序,当我启动它时,我担心潜在的multithreading问题。 一个特别关注的是以下代码:
private static IDictionary _settingsDictionary = new Dictionary(); public T Settings() where T : ISettings, new() { var key = typeof(T).FullName; if (!_settingsDictionary.ContainsKey(key)) _settingsDictionary[key] = _settingsService.GetSettings(); return (T)_settingsDictionary[key]; }
请注意,字典定义为静态。 这允许我缓存字典,以便它为应用程序长度的每个请求返回相同的实例。
这在本地测试时工作正常,但我担心它可能会被数百名用户使用。 这使我开始研究ConcurrencyDictionary。 请问你能告诉我是否需要使用它以及如果是这样我会怎么做。
谢谢
是的,这里有潜在的数据竞争:
if (!_settingsDictionary.ContainsKey(key)) _settingsDictionary[key] = _settingsService.GetSettings();
这可能会导致两个线程添加相同的密钥,因为它们可以在任何时候中断。
您可以使用ConcurrentDictionary.GetOrAdd代替:
private static ConcurrentDictionary _settingsDictionary = new ConcurrentDictionary(); public T Settings() where T : ISettings, new() { var key = typeof(T).FullName; return _settingsDictionary.GetOrAdd(key, _settingsService.GetSettings ()); }
编辑 :由于您不希望每次都执行_settingsService.GetSettings
,因此可以选择:
private static IDictionary _settingsDictionary = new Dictionary(); private static object locker = new object(); public T Settings() where T : ISettings, new() { var key = typeof(T).FullName; lock(locker) { if (!_settingsDictionary.ContainsKey(key)) _settingsDictionary[key] = _settingsService.GetSettings (); return (T)_settingsDictionary[key]; } }
是的,有一场比赛,因为如果没有找到钥匙:
if (!_settingsDictionary.ContainsKey(key))
然后到我们运行时:
_settingsDictionary[key] = _settingsService.GetSettings();
可能有一把钥匙。
它甚至比不必要地更换更糟糕。 如果添加密钥的线程1需要resize,那么当线程2添加并且它被认为需要resize时它可能是部分通过,并且几乎所有的注意都被关闭以用于该字典的任何进一步使用。
重要的问题是,“这是一个案例,我们将有很multithreading同时击中字典,或者这是一个罕见但我们需要防范它的情况?”
在第一种情况下,使用ConcurrentDictionary。 在第二种情况下,只需为当前代码添加锁定即可。 ConcurrentDictionary在并发性方面提供了更好的性能(正如人们对名称所期望的那样),但是当通常只有一个线程实际命中它时,围绕普通字典的锁定会更好,但偶尔的并发调用是可能的。
替代两者,如果可能的设置数量很少,只需在开头加载批次。 如果没有更多的写作,字典对于多个读者是安全的,并且对于零锁定来说,这是最快的。
- ASP.NET MVC表单post
- 如何使用DI在Class Constructor中获取Microsoft.AspNet.Http.HttpContext实例
- ASP MVC.NET – 如何绑定KeyValuePair?
- 在Asp.net MVC 4中指定area属性时,ActionLink和Url.Action将定位不同的位置
- 将AjaxOnlyAttribute和ChildActionOnlyAttribute组合到一个动作filter中
- 将XML解析列表从控制器传递到ASP.NET MVC中的视图
- 控制器错误“Microsoft.AspNetCore.Mvc.Rendering.SelectListItem”中的MVC Core SelectList下拉列表
- ASP.NET MVC 2中具有一个名称的多个控制器
- Asp.Net中Task.Run和QueueBackgroundWorkItem之间的区别