如果我不打算在添加元素时从列表中读取,是否有必要在向 C# 列表添加元素之前锁定 C# 列表
本文关键字:列表 元素 添加 锁定 是否 读取 如果 | 更新日期: 2023-09-27 18:32:44
这是一个MWE:
Func<Int32, Boolean> MyFunc = (s) => {
var res = false;
// Insert function logic to modify the value to res
return res;
};
var Result = new List<Int32> ();
var LockObj = new Object ();
ParallelEnumerable.Range (1, 100000)
.ForAll (s => {
if (MyFunc (s)) {
lock (LockObj) { // IS THIS NECESSARY?
Result.Add (s);
} // End lock
}
});
这就是情况的归结。 如果我不打算在 ParallelEnumerable 语句完成执行之前查询它,我认为我不需要锁定 Result 是否正确?
请注意:我知道 MWE 最好通过"Where"子句来解决,如下所示:
ParallelEnumerable.Range (1, 100000)
.Where (s => MyFunc (s));
但由于MWE中不明显的原因,这是不可能的。
编辑
感谢所有回答的人。 也感谢您的评论。 我已经纠正了董发现的错误。
是的,你必须lock
.并行 将导致并发调用Add()
。
附带说明一下:
//var Result = new List<Int32> ();
var Result = new List<Int32> (100000);
ParallelEnumerable.Range (1, 100000)
将使这更有效率。更少的增长也意味着更少的lock
竞争。
添加到泛型列表不是线程安全的。锁定是一种可能性。您还可以使用 im .Net 4.0 引入的线程安全集合类型之一
查看并行 for 循环 - 添加到列表时的问题以获取更多信息
可以通过选择现有的并行集合之一来消除大量争用:
ConcurrentBag<int> bag=new ConcurrentBag<int>();
ParallelEnumerable.Range(0,10000).ForAll(s => {if(MyFunc(s)) bag.Add(s);});
使用 Semaphore.it 将管理对共享资源的访问(在您的情况下为通用列表)。