【发布时间】:2015-10-18 04:43:02
【问题描述】:
如果我先发布代码会更容易:
static void Main(string[] args)
{
List<double> testLst = new List<double>();
for (int i = 0; i < 20000000; i++) { testLst.Add(i); }
我已经填充了一个包含 20,000,000 个元素的列表。我在任务管理器中看到该进程正在使用 ~300MB。如果我使用 foreach 循环遍历列表:
foreach (var a in testLst.Take(10))
{
Console.WriteLine(a);
}
}
内存使用量没有增加(我在 Console.WriteLine 上设置了一个断点,正如我所说,我正在使用任务管理器对其进行测量)。现在,如果我用 ConcurrentBag 替换 List:
static void Main(string[] args)
{
ConcurrentBag<double> testCB = new ConcurrentBag<double>();
for (int i = 0; i < 20000000; i++) { testCB.Add(i); }
foreach (var a in testCB.Take(10))
{
Console.WriteLine(a);
}
}
foreach-loop 之前的内存使用量为 450~500MB。问题是:为什么如果在 foreach 循环内部使用量跃升至 ~900MB?
我希望 ConcurrentBag 与 List 相比消耗更多内存,但我不明白为什么要使用这么多内存进行迭代。
(我在类似但不同的场景中使用 ConcurrentBag,我知道在这种情况下使用它没有意义)
【问题讨论】:
-
ConcurrentBag 在创建迭代器时需要拍摄某种快照——因此更高的内存使用率似乎是合理的。检查参考源代码以查看详细信息...
-
长话短说:从不迭代线程安全的集合。它会吞噬内存并且您获得的值通常是陈旧的。如果您需要可预测的结果,那么 lock 关键字是无可替代的。