如何正确使用并行计算对集合进行写操作?
2011-04-03 17:47
776 查看
using System; using System.Collections.Generic; using System.Collections.Concurrent; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Diagnostics; namespace ParallelTest1 { public class CalcTask { public event EventHandler<TaskItemEventArgs> OnTaskFinish; public void ExecuteTasks() { int icount = 100; List<Task> items = new List<Task>(icount); PInitializeTask(items, icount); Console.WriteLine(items.Count); List<Task> items2 = new List<Task>(); SInitializeTask(items2, icount); Console.WriteLine(items2.Count); Console.ReadKey(); } private void PInitializeTask(List<Task> items,int iCount) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); Parallel.For(0, iCount, new ParallelOptions() { }, i => { lock (items) //如果不加锁,观察最终集合的个数? { items.Add(new Task() { Source = i, Dest = i + i, }); //if (items.Count == iCount) OnTaskFinish(this, new TaskItemEventArgs() { ThreadId=Thread.CurrentThread.ManagedThreadId, Data=items, }); } }); stopwatch.Stop(); Console.WriteLine("Parallel loop time in milliseconds: {0}", stopwatch.ElapsedMilliseconds); } private void SInitializeTask(List<Task> items, int iCount) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); for(int i=0;i<iCount;i++) { items.Add(new Task() { Source = i, Dest = i + i, }); OnTaskFinish(this, new TaskItemEventArgs() { ThreadId = Thread.CurrentThread.ManagedThreadId, Data = items, }); } stopwatch.Stop(); Console.WriteLine("Sequential loop time in milliseconds: {0}", stopwatch.ElapsedMilliseconds); } } public class Task { public int Source { get; set; } public int Dest { get; set; } public override string ToString() { return string.Format("{0}-{1}", this.Source, this.Dest); } } public class TaskItemEventArgs:EventArgs { public int ThreadId{get;set;} public object Data{get;set;} } }
static void Main(string[] args) { Console.WriteLine("Processor Count:" + Environment.ProcessorCount); CalcTask task1 = new CalcTask(); task1.OnTaskFinish += new EventHandler<TaskItemEventArgs>((sender, e) => { Console.WriteLine(string.Format("Finish:{0}-{1}", e.ThreadId, (e.Data as List<Task>).Count)); }); task1.ExecuteTasks(); }
在上述代码中,我测试的结果规律如下:
如果并行中,不加lock,如果是向集合填充100万个对象 ,那么并行代码 执行完毕后,那个集合的数目永远都是小于100万,我的结果显示是80多万。。。。估计中间发生冲突导致部分的项添加不成功,但是.net并没有报错,这样很容易让我们中招。所以用一般集合时需要小心,这里也证实了一般的集合List<T>并不是线程安全的。。。
后来我换成System.Collections.Concurrent.ConcurrentDictionary<int, Task>试了下,发现不用加lock,结果也是正确的,所以大家在并行运算中记得多使用这个哈希结构。。。但是线程安全的。
相关文章推荐
- BeJavaGod - 如何正确使用数据字典进行分类统一操作(一)
- BeJavaGod - 如何正确使用数据字典进行分类统一操作(一)
- 如何使用pssh进行并行批量操作
- 如何在一台电脑上使用两个git@osc的账号进行操作
- Dojo 1.6 最新官方教程: 如何使用dojo.query 进行DOM查询和批量操作
- 在verilog中使用clogb2函数可进行log2操作,用来计算数据位宽
- 操作分布式文件之四:如何进行集群内文件复制和并行复制
- 使用pssh进行并行批量操作
- DDD 领域驱动设计-Value Object(值对象)如何使用 EF 进行正确映射
- Dojo 1.6 最新官方教程: 如何使用dojo.query 进行DOM查询和批量操作
- MySQL使用集合函数进行查询操作实例详解
- java如何对map进行排序详解(map集合的使用)
- 使用Iterator方式对集合进行remove/add 操作
- Elasticsearch:如何使用正确的姿势进行搜索
- 用 ConTest 进行多线程单元测试 - 为什么并行测试很困难以及如何使用 ConTest 辅助测试
- [How To]如何使用Wildfish进行ISeries开发---多操作篇
- 如何使用文件的fseek函数对文件指针进行操作
- 如何正确的进行大规模SQL语句的批量操作
- Aicken教你做测试之使用并行计算进行单元测试
- java 如何使用缓冲区对文件进行读写操作