前面说在练习Parallel时,发现另有乾坤,是这样的代码:

代码

static IEnumerable<Person> testFill()
{
var list =new List<Person>(9);

Enumerable.Range(1, 99999).ToList().ForEach(n =>
{
var name ="Person"+ n %9;
list.Add(new Person { Id = n, Name = name });
});
Console.WriteLine("Person's count is {0}", list.Count);
return list;
}

static IEnumerable<Person> testFillParallel()
{
var list =new List<Person>(9);

Enumerable.Range(1, 99999).AsParallel().ForAll(n =>
{
var name ="Person"+ n %9;
list.Add(new Person { Id = n, Name = name });
});
Console.WriteLine("Person's count is {0}", list.Count);
return list;
}

class Person
{
internalint Id { get; set; }
internalstring Name { get; set; }
}

  试验结果如下(单位ms):

次数

1

2

3

4

Fill 方法

37

27

26

26

FillParallel 方法

43

20

19

20

  这个结果有点奇妙的。第一次多线程居然还不如单线程快,和上文例子比较一下,有点明白了。稍微改了下代码,在Add语句前加了个Thread.Sleep(1),并把 List<Person>集合元素减为999,试了一次,结果如下(单位ms):

次数

1

2

3

4

Fill 方法

1012

998

998

999

FillParallel 方法

547

504

504

504

  多个线程协同工作时,分配任务本身有开销,要是分配的开销比任务本身还大,多线程就没有意义了。就比如你交待别人做某件事,要是交待的功夫比自己做还长,还不如自己做。不过从结果也可以看出一个辩证关系,从长远打算,第一次让别人熟悉业务,付出点培训成本,执行完一次后,以后就轻松多了,速度提高了一倍。如果这里Sleep一下,模拟长一点的单次处理过程,一开始多线程的优势就会非常明显。

  FillParallel方法,大家觉得有没有其它问题呢?想必一般人都能看出,这里有最初级的线程安全问题。没看出的应该是刚学.Net各种集合的初学者,线程安全对他们还只是个太虚幻境。不过借助这个Parallel,就可以轻松神游幻境。把FillParallel方法循环一百次执行,会发现返回结果本来应该有999个元素,输出的却显示却结果经常少十几二十个。如果创建List时赋的容量不够,在List扩容时,还可能引发异常。一般是像下图这样(不过一百次都是999也不是不可能,要看你的RP了):

  应提醒一点的是,试验要在Release编译模式下运行,不然看不到线程安全问题,并行执行的效率提升得也很有限。我用的电脑都是双核,不知道在单核电脑的运行情况如何,可能有一定区别。

  接着我改下逻辑,增加了一个是否Person存在重名的判断,变成:

代码

static IEnumerable<Person> testFillParallel()
{
var list =new List<Person>(9);

Enumerable.Range(1, 999).AsParallel().ForAll(n =>
{
var name ="Person"+ n %9;
if (list.Count(p => p.Name == name) <1) list.Add(new Person { Id = n, Name = name });
});
Console.WriteLine("Person's count is {0}", list.Count);
return list;
}

  RP不管用了,执行几次,必抛异常:System.InvalidOperationException: Collection was modified; enumeration operation may no execute.

  一个线程在枚举集合元素,这时必须保证集合不被其它线程修改,怎么办呢?以前,就知道用锁,现在据说有了线程安全的集合类,在System.Collections.Concurrent命名空间下,有ConcurrentDictionary, ConcurrentQueue, ConcurrentStack,就是没有ConcurrentList。费了半天,才发现与List对应的应该是BlockingCollection。

  把集合定义换成: var list = new BlockingCollection<Person>(9); 只见刷刷刷,哪怕执行几万次都可以一路跑完了。

  不过这样做,还是会发现问题,不知大家看出了吗?

.Net 4.0并行库实用性演练相关推荐

  1. .Net 4.0并行库实用性演练[1]

    自VS2010发布近半年了,虽然整天想学习新东西,要更新到自己时,发现原来自己基本也很懒,2008还没用上多久呢,无奈被2010了.用了几天,IDE模样还是和05.08差不多,加了些小特性,以后慢慢体 ...

  2. Net 4.0并行库实用性演练

    引言 随着CPU多核的普及,编程时充分利用这个特性越显重要.上篇首先用传统的嵌套循环进行数组填充,然后用.NET 4.0中的System.Threading.Tasks提供的Parallel Clas ...

  3. .Net4.0并行库介绍——Cancellation Framework

    在.net 4.0中,引入了一个新的类CancellationToken,这个类基本上集成了我们各种常用的取消方式,在并发任务中非常有用. 同步模式下的取消: 一种比较常见的需要支持取消功能的的是一些 ...

  4. .NET4.0并行计算技术基础(8)

    说明: 要想看懂本系列文章,需要您对.NET多线程开发有基本的了解.我在新书<面向对象的艺术 --.NET Framework 4.0技术剖析与应用>(暂名)中花了近200页的篇幅来介绍. ...

  5. 多线程编程学习笔记——任务并行库(二)

    接上文 多线程编程学习笔记--任务并行库(一) 三.   组合任务 本示例是学习如何设置相互依赖的任务.我们学习如何创建一个任务的子任务,这个子任务必须在父任务执行结束之后,再执行. 1,示例代码如下 ...

  6. 多线程编程学习笔记——任务并行库(三)

    接上文 多线程编程学习笔记--任务并行库(一) 接上文 多线程编程学习笔记--任务并行库(二) 六.   实现取消选项 本示例学习如何实现基于Task的异步操作进行取消流程,以及在任务真正运行前如何知 ...

  7. C#多线程开发-任务并行库

    你好,我是阿辉. 正文共2090字,预计阅读时间:6min. 之前学习了线程池,知道了它有很多好处. 使用线程池可以使我们在减少并行度花销时节省操作系统资源.可认为线程池是一个抽象层,其向程序员隐藏了 ...

  8. 三分钟总览微软任务并行库TPL

    点击上方蓝字进行关注 有小伙伴问我每天忽悠的TPL是什么? ☹️ 这次站位高一点,严肃讲一讲. 引言 俗话说,不想开飞机的程序员不是一名好爸爸:作为微软技术栈的老鸟,一直将代码整洁之道奉为经典, 优秀 ...

  9. .NET异步程序设计之任务并行库

    目录 1.简介 2.Parallel类 2.0 Parallel类简介 2.1 Parallel.For() 2.2 Parallel.ForEach() 2.3 Parallel.Invoke() ...

最新文章

  1. python代码大全o-Python简单I/O操作示例
  2. java中ssh如何理解
  3. c# 学习笔记 (1) 类型转换
  4. 备战2020腾讯广告算法大赛:(2017-2019比赛开源和数据等)
  5. CentOS 关闭、启动网卡
  6. PHP Collection 类
  7. 史上最详细 纯CSS打造3D文本滚动
  8. c语言值传递 地址传递 引用传递参数,C++参数传递(值传递,引用传递)
  9. python绘图函数m_Python散点图。m的尺寸和样式
  10. Keras框架:人脸检测-mtcnn思想及代码
  11. ASP.Net防止页面刷新重复提交
  12. 小程序 | 保存图片时处理名称的细节(时间戳+后缀名)
  13. PHP基础知识之文件加载
  14. mysql mha好吗_MySQL高可用方案MHA的一些总结和思考
  15. 牛掰!某厂风控大佬整理的一套黑客学习思维导图及教程!
  16. ss客户端以及tcp,udp,dns代理ss-tproxy本地安装版--centos7.3 x64以上(7.3-7.6x64测试通过)...
  17. 最新国产操作系统uos一小时使用体验
  18. Cepton宣布与美国底特律顶级汽车制造商合作,赢得业内最大ADAS激光雷达量产订单
  19. Ubuntu 14.04出现“device not managed”错误及ubuntu可以ping通外网浏览器上不了网。
  20. (比较器)Comparator比较器

热门文章

  1. [PTA]L2-001 紧急救援 (25 分)
  2. 简易OA漫谈之工作流设计(四,怎么支持会签)
  3. WCF、WebAPI、WCFREST、WebService之间的区别
  4. Velocity 页面加减运算
  5. lua IDE all
  6. JAVA学习笔记-“Hello World”
  7. Nodejs读写文件
  8. 无法解决 equal to 运算中 Chinese_PRC_CI_AS 和 SQL_Latin1_General_CP1_CI_AS 之间的排序规则冲突。...
  9. 关于mobile中datagrid的使用
  10. mysql 中模糊查询的四种用法介绍