C# 是否可以确定列表操作是否是线程安全的?

C# 是否可以确定列表操作是否是线程安全的?,c#,multithreading,linq,C#,Multithreading,Linq,如果X、X.Code和X.Rate的两个属性与ListB中任何元素Y的代码和速率匹配,我将尝试对列表ListA中的每个元素X进行比较。当前的解决方案使用LINQ和AsParallel来执行这些比较时间是一个因素,每个列表可以包含0个元素到几百个元素 到目前为止,AsParallel方法似乎要快得多,但是我不确定这些操作是否是线程安全的。我的理解是,因为这种比较只是读取值,而不是修改值,所以这应该是安全的,但我不是100%有信心。在我的生产环境中释放此操作之前,如何确定它是否是线程安全的 以下是我

如果X、X.Code和X.Rate的两个属性与ListB中任何元素Y的代码和速率匹配,我将尝试对列表ListA中的每个元素X进行比较。当前的解决方案使用LINQ和AsParallel来执行这些比较时间是一个因素,每个列表可以包含0个元素到几百个元素

到目前为止,AsParallel方法似乎要快得多,但是我不确定这些操作是否是线程安全的。我的理解是,因为这种比较只是读取值,而不是修改值,所以这应该是安全的,但我不是100%有信心。在我的生产环境中释放此操作之前,如何确定它是否是线程安全的

以下是我正在使用的代码:

var s1 = System.Diagnostics.Stopwatch.StartNew();
ListA.AsParallel().ForAll(x => x.IsMatching = ListB.AsParallel().Any(y => x.Code== y.Code && x.Rate== y.Rate));
s1.Stop();


var s2 = System.Diagnostics.Stopwatch.StartNew();
ListA.ForEach(x => x.IsMatching = ListB.Any(y => x.Code == y.Code && x.Rate== y.Rate));
s2.Stop();

目前,每个方法都返回相同的结果,但是AsParallel的执行时间约为普通ForEach的1/3,因此如果有安全执行此操作的方法,我希望从中获益。

您的代码是线程安全的。列表是以只读方式访问的,实现并行化版本所需的隐式同步足以确保已提交任何写操作。您确实修改了列表中的元素,但同样,并行操作中隐含的同步(当前线程必须等待)将确保对元素对象的任何写入都在当前线程中可见

这就是说,线程安全性是无关紧要的,因为你做的事情都是错的。您正在对一个需要应用蛮力^2算法,该需要可以使用更优雅、更高效的解决方案LINQ join来解决:

您的代码示例未包含任何示例数据的初始化。所以我不能以任何可靠性重现你的结果。事实上,在我的测试集中,我对list1和list2进行了相同的初始化,每个都有相同的1000个元素,我只需将代码和速率设置为列表中元素的索引,即0到999,我发现AsParallel版本比串行版本慢,比25%多一点,即并行版本的250次迭代大约需要2.7秒,而串行版本的250次迭代大约需要1.9秒

但两者都没有接近join版本,join版本在大约60毫秒内完成了250次特定测试数据的迭代,比其他两种实现的速度快了近20倍


我有理由相信,尽管我缺乏与您的场景相关的可比数据集,但基本结果仍然有效,并且您会发现使用联接方法远远优于您迄今为止尝试过的任何一种方法。

您拥有的代码是线程安全的。列表是以只读方式访问的,实现并行化版本所需的隐式同步足以确保已提交任何写操作。您确实修改了列表中的元素,但同样,并行操作中隐含的同步(当前线程必须等待)将确保对元素对象的任何写入都在当前线程中可见

这就是说,线程安全性是无关紧要的,因为你做的事情都是错的。您正在对一个需要应用蛮力^2算法,该需要可以使用更优雅、更高效的解决方案LINQ join来解决:

您的代码示例未包含任何示例数据的初始化。所以我不能以任何可靠性重现你的结果。事实上,在我的测试集中,我对list1和list2进行了相同的初始化,每个都有相同的1000个元素,我只需将代码和速率设置为列表中元素的索引,即0到999,我发现AsParallel版本比串行版本慢,比25%多一点,即并行版本的250次迭代大约需要2.7秒,而串行版本的250次迭代大约需要1.9秒

但两者都没有接近join版本,join版本在大约60毫秒内完成了250次特定测试数据的迭代,比其他两种实现的速度快了近20倍


我有理由相信,尽管我缺乏与您的场景相关的可比数据集,但基本结果仍然有效,并且您会发现使用联接方法远远优于您迄今为止尝试过的任何一种方法。

根据的线程安全部分,是的。我是个白痴,我正在用x.IsMatching赋值,这是否会影响您的答案@AndrewMorton?将“是”更改为“不保证”。但是,您没有添加或删除元素,并且这些指定不会影响其他元素中已读取的部分,因此看起来您处于安全状态。好的,谢谢!如果你想从你的评论中写出一个答案,我会毫不犹豫地把它标记为被接受的答案,我宁愿不写
请不要把我的评论作为答案,因为我不确定这是一个好答案。我希望其他人会插话是的,安德鲁是对的,或者安德鲁在胡说八道。如果你想,你可以自己写下来作为答案并接受。根据的线程安全部分,是的。我是个白痴,我用x.IsMatching赋值,这会影响你的答案@AndrewMorton吗?将“是”改为“不保证”。但是,您没有添加或删除元素,并且这些指定不会影响其他元素中已读取的部分,因此看起来您处于安全状态。好的,谢谢!如果你想从你的评论中写出一个答案,我将毫无问题地将其标记为已接受的答案。我宁愿不将我的评论作为答案发布,因为我不太确定这是一个好答案。我希望其他人会插话是的,安德鲁是对的,或者安德鲁在胡说八道。如果你想,你可以自己写下来作为答案,然后接受它。
var join = from x in list1
           join y in list2 on new { x.Code, x.Rate } equals new { y.Code, y.Rate }
           select x;

foreach (A a in join)
{
    a.IsMatching = true;
}