gpt4 book ai didi

c# - 极端线程安全集合

转载 作者:太空狗 更新时间:2023-10-30 00:50:21 25 4
gpt4 key购买 nike

我在 .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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com