当前位置: 首页 > news >正文

.Net 4.0并行库实用性演练

  前面说在练习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
{
internal int Id { get ; set ; }
internal string 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); 只见刷刷刷,哪怕执行几万次都可以一路跑完了。

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

转载于:https://www.cnblogs.com/XmNotes/archive/2010/09/08/1821627.html

相关文章:

  • 批量创建域用户
  • 驱动开发基础资料
  • 浅析dev目录下设备文件mknod节点gid,uid和mode的如何方便设置
  • 短信1
  • [Share]商务web应用程序的界面设计
  • 数据类型,运算符和表达式04 - 零基础入门学习C语言05
  • python无缓存(转载)
  • 使用windows crypto API加密解密
  • MyEclipse环境下Hibernate入门实例
  • 彻底弄懂CSS盒子模式
  • Linux启动流程
  • 按类别DF特征词选择算法
  • Dell Insprion 6400坏
  • Makefile相关资料
  • 浅谈角色与权限
  • [nginx文档翻译系列] 控制nginx
  • 【Linux系统编程】快速查找errno错误码信息
  • 2017-09-12 前端日报
  • Android 控件背景颜色处理
  • exif信息对照
  • Invalidate和postInvalidate的区别
  • js正则,这点儿就够用了
  • js中的正则表达式入门
  • python 装饰器(一)
  • 测试如何在敏捷团队中工作?
  • 发布国内首个无服务器容器服务,运维效率从未如此高效
  • 基于Mobx的多页面小程序的全局共享状态管理实践
  • 紧急通知:《观止-微软》请在经管柜购买!
  • 前端相关框架总和
  • 悄悄地说一个bug
  • 实现简单的正则表达式引擎
  • LIGO、Virgo第三轮探测告捷,同时探测到一对黑洞合并产生的引力波事件 ...
  • 说说我为什么看好Spring Cloud Alibaba
  • ​ArcGIS Pro 如何批量删除字段
  • #多叉树深度遍历_结合深度学习的视频编码方法--帧内预测
  • (a /b)*c的值
  • (Demo分享)利用原生JavaScript-随机数-实现做一个烟花案例
  • (pojstep1.3.1)1017(构造法模拟)
  • (附源码)springboot 智能停车场系统 毕业设计065415
  • (个人笔记质量不佳)SQL 左连接、右连接、内连接的区别
  • (更新)A股上市公司华证ESG评级得分稳健性校验ESG得分年均值中位数(2009-2023年.12)
  • (一) springboot详细介绍
  • (原創) 如何安裝Linux版本的Quartus II? (SOC) (Quartus II) (Linux) (RedHat) (VirtualBox)
  • (中等) HDU 4370 0 or 1,建模+Dijkstra。
  • .NET 编写一个可以异步等待循环中任何一个部分的 Awaiter
  • .NET 依赖注入和配置系统
  • .NET/ASP.NETMVC 深入剖析 Model元数据、HtmlHelper、自定义模板、模板的装饰者模式(二)...
  • .net开发引用程序集提示没有强名称的解决办法
  • @configuration注解_2w字长文给你讲透了配置类为什么要添加 @Configuration注解
  • @GlobalLock注解作用与原理解析
  • @param注解什么意思_9000字,通俗易懂的讲解下Java注解
  • @transactional 方法执行完再commit_当@Transactional遇到@CacheEvict,你的代码是不是有bug!...
  • [ IOS ] iOS-控制器View的创建和生命周期
  • [《百万宝贝》观后]To be or not to be?
  • [2019.3.20]BZOJ4573 [Zjoi2016]大森林