项目中出了个 BUG,就在我眼皮子底下,很明显的一个 BUG,愣是看了两天才看出来。
我有多个任务并发,任务执行完成后都有一个返回结果,我用一个 List
将结果收集起来,等所有任务完成后,发送出去。结果一直 丢数据。
我反复检查逻辑都没有问题,最后恍然 List
是非线程安全的。
大家都知道 List
是非线程安全的,但是如果仅有 Add
操作呢?估计有些人就会认为没问题。
下面的代码,期望输出的结果是 1000,然而,注释掉 lock
后,结果就不一样了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
class Program { static List<Person> persons; static void Main( string [] args) { persons = new List<Person>(); object sync = new object (); Parallel.For(0, 1000, (i) => { Person person = new Person { ID = i, Name = "name" + i }; lock (sync) persons.Add(person); }); Console.WriteLine(persons.Count); Console.ReadLine(); } class Person { public int ID { get ; set ; } public string Name { get ; set ; } } } |
利用安全集合ConcurrentBag取代list
测试程序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MyConcurrent { class Program { /// <summary> /// ConcurrentBag并发安全集合 /// </summary> public static void ConcurrentBagWithPallel() { ConcurrentBag< int > list = new ConcurrentBag< int >(); Parallel.For(0, 10000, item => { list.Add(item); }); Console.WriteLine( "ConcurrentBag's count is {0}" , list.Count()); int n = 0; foreach ( int i in list) { if (n > 10) break ; n++; Console.WriteLine( "Item[{0}] = {1}" , n, i); } Console.WriteLine( "ConcurrentBag's max item is {0}" , list.Max()); } /// <summary> /// 函数入口 /// </summary> /// <param name="args"></param> static void Main( string [] args) { Console.WriteLine( "ConcurrentBagWithPallel is runing" ); ConcurrentBagWithPallel(); Console.Read(); } |
以上就是C# List 并发丢数据问题原因及解决方案的详细内容,更多关于C# List 并发丢数据的资料请关注服务器之家其它相关文章!
原文链接:https://www.cnblogs.com/gl1573/p/14392108.html