如何正确使用并行计算对集合进行写操作?

 
  
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,结果也是正确的,所以大家在并行运算中记得多使用这个哈希结构。。。但是线程安全的。

转载于:https://www.cnblogs.com/yulinlover/archive/2011/04/03/2004515.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值