c# - 我应该更喜欢并发集合而不是每个线程的传统集合吗?
问题描述
我基本上是在尝试static List<T>
通过方法调用将一些项目(大约 100000 个 T 实例)插入(Common.VariablesList),例如
a.SomeMethoad(); b.SomeMethod; c.SomeMethod; d.SomeMethod();
a, b, c & d 继承自一个公共抽象类。我向它们的父抽象类添加了一个实例属性VariablesList<T>
,并开始将项目插入实例列表而不是公共列表,以便我可以使用 Parallel.Invoke 并行调用这些方法。之后Parallel.Invoke
,我只是将所有这些列表添加到 Common.VariableList。
Common.VariableList.AddRange(a.VariableList);
Common.VariableList.AddRange(b.VariableList);
Common.VariableList.AddRange(c.VariableList);
Common.VariableList.AddRange(d.VariableList);
我最近阅读了有关并发集合的信息,例如ConcurrentBag<T>
,我应该更改代码以使用并发集合还是保持实现不变?我的意思是哪一个在编程的最佳实践中更受青睐?
解决方案
因此,假设每个都SomeMethod
使用自己的数据对不同的对象进行操作,那么使用 Parallel.Invoke 同时调用其中的 4 个是没有危险的。您不需要进行任何同步、编组或锁定。这就像告诉 4 个面包师每人烤 1 个蛋糕,每个蛋糕都有自己独立的配料、器具和烤箱。他们可以完全独立工作。
通过在SomeMethod
同步(并发/线程安全)集合中创建集合,您实际上是在引入开销来保护自己免受永远不会发生的情况的影响。每个面包师现在必须在接触他们的任何工具或配料之前,问“还有其他人在用我的勺子吗?” 并宣布“我在用我的勺子!” 并宣布“我不再使用我的勺子”。实际上,有 4 个勺子,没有其他人会碰你的勺子、蛋糕粉或烤箱。因此,无需同步即可工作。
继续进行类比,假设这个想法是让每个面包师烘烤一层 4 层蛋糕,然后当他们全部完成后,第五个面包师将所有 4 层组装成最终蛋糕。
在这种情况下,你是第五个面包师,你来主持节目。
您指示其他 4 位面包师分别烘烤他们的蛋糕。a.SomeMethod()
您可以通过使用、b.SomeMethod()
、c.SomeMethod()
和并行调用 Parallel.Invoke 来做到这一点d.SomeMethod
。当这个方法完成后,你就知道“四个蛋糕都准备好了”。此时,您将完成将蛋糕堆叠成单层蛋糕的剩余工作。你打电话:
Common.VariableList.AddRange(a.VariableList);
Common.VariableList.AddRange(b.VariableList);
Common.VariableList.AddRange(c.VariableList);
Common.VariableList.AddRange(d.VariableList);
这是我的意思的完整示例:
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
class Baker
{
List<string> myList = new List<string>();
public string Bake(string flavor)
{
for (int i = 0; i < 5; ++i)
{
myList.Add(flavor); // free to modify local data without synchronization
}
return string.Join("", myList);
}
}
class Program
{
static string Icing(string layer)
{
return new string('~', layer.Length) + Environment.NewLine + layer + Environment.NewLine;
}
static void Main(string[] args)
{
Baker a = new Baker();
Baker b = new Baker();
Baker c = new Baker();
Baker d = new Baker();
string cake_a = null;
string cake_b = null;
string cake_c = null;
string cake_d = null;
Parallel.Invoke(
() => { cake_a = a.Bake("*cherry*"); },
() => { cake_b = b.Bake("*orange*"); },
() => { cake_c = c.Bake("*banana*"); },
() => { cake_d = d.Bake("*choco**"); }
);
string layer_cake = Icing(cake_a) + Icing(cake_b) + Icing(cake_c) + Icing(cake_d);
Console.WriteLine(layer_cake);
}
}
所以希望这说明最好使用每个对象的非同步集合来保持低开销(不需要与其他面包师交谈,因为他们没有使用你的东西)并且只依赖于 Parallel.Invoke 如何在内部同步到让您知道所有任务何时完成。并在另一个线程中进行合并操作(可能是第五个工作线程,或者只是主线程,这取决于程序中发生的其他事情。)
推荐阅读
- jquery - Jquery - 附加到 id 以使用 each 开头的所有元素
- flutter - 在reales模式下在android中使用flutter 1.17.1后应用折痕
- c++ - 在 Visual C++ 64 位 dll 中启用视觉样式不起作用
- c++ - 将 XPS 字节流式传输到打印文档包 API
- php - 按包含数字和单词的值对多维数组进行排序
- java - 何时在休眠中使用 transaction.rollback()
- r - 时间序列的分层预测,包括缺失值 (R)
- reactjs - 如何在 useEffect 挂钩中使用函数参数
- python - 如何在 Pyqt5 Python 的 QTableWidget 的列过滤器中添加搜索栏?
- r - browseVignettes 没有为 R 中的 ggplot2 包返回任何内容 - 没有错误消息