- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我在 .Net 4.5 中有一个 ConcurrentBag,我从数据库中存储了大约 4,000 行。我正在存储 DTO。
我的整个应用程序都依赖于此。我有返回整个列表的函数,也有返回单个项目的函数。我在代码中的很多地方都在对集合等进行 LINQ 查询。
我将其全部推向生产环境,在获得可观流量的网站上,并立即 100% cpu。我用了iis诊断工具,果然有50+线程死锁,等待ConcurrentBag。
文档说这个集合是线程安全的,但要么这不是真的,要么这个集合的性能不好从而间接地使其不是线程安全的。
不幸的是,这个集合不是只读的。如果按 ID 查找的函数之一返回 null,它将访问 Web 服务并添加它。
我也将它转换为 ConcurrentDictionary,但遇到了同样的问题。在 .Values 属性上锁定 Days。
在最极端的情况下,最快和最线程安全的解决方案是什么?
private ConcurrentBag<Students> _students;
public static ConcurrentBag<DestinyHash> GetStudents()
{
if (_students == null) { _students = new ConcurrentBag<Students>(); }
return _students;
}
public static Student GetStudentByID(int id)
{
if (GetStudents().Any(x => x.id == id)) { return ... }
_students.Add(getStudentFromDb(id));
return...
}
示例用法 - 遍及整个应用程序。
Helper.GetStudents().FirstOrDefault(x => x.name == "foo" && x.status == "bar");
Helper.GetStudentByID(50);
最佳答案
简单的答案是您使用了错误的容器。
ConcurrentBag
不是通用的。它更像是一个可重用对象池,您可以(通常作为最后一步)将其缩减为单个非并发值。它可用于解决的一个此类问题是同时对列表求和。
如果您主要使用 ConcurrentBag
偏离添加/删除,并且您经常枚举集合,那么您使用它是错误的。
如果您发布更多代码,您将获得更有针对性的帮助。并发性是理解问题对于提供高性能解决方案非常重要的领域之一。
编辑:
ConcurrentDictionary
将为您正在做的事情工作。诀窍是你不想使用 ConcurrentDictionary.Values
-- 这将锁定字典并复制其内容。如果你只是使用它的 IEnumerable<T>
接口(interface),你会没事的。例如:
private ConcurrentDictionary<int,Student> _students;
public static IEnumerable<Student> GetStudents()
{
return _students.Select(x => x.Value);
}
public static Student GetStudentByID(int id)
{
Student s;
if(_students.TryGetValue(id, out s)) return s;
s = getStudentFromDb(id);
_students[id] = s;
return s;
}
关于c# - 极端线程安全集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32029956/
我正在寻找绘制极坐标数据的替代方法。我需要实现像 this 这样的图表具有动态选项,例如 this . 非常感谢您的帮助! 最佳答案 我个人需要这些: Highcharts JS canvasXpre
我是一名优秀的程序员,十分优秀!