.Net 4.0并行库实用性演练
前面说在练习Parallel时,发现另有乾坤,是这样的代码:
{
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存在重名的判断,变成:
{
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并行库实用性演练相关推荐
- .Net 4.0并行库实用性演练[1]
自VS2010发布近半年了,虽然整天想学习新东西,要更新到自己时,发现原来自己基本也很懒,2008还没用上多久呢,无奈被2010了.用了几天,IDE模样还是和05.08差不多,加了些小特性,以后慢慢体 ...
- Net 4.0并行库实用性演练
引言 随着CPU多核的普及,编程时充分利用这个特性越显重要.上篇首先用传统的嵌套循环进行数组填充,然后用.NET 4.0中的System.Threading.Tasks提供的Parallel Clas ...
- .Net4.0并行库介绍——Cancellation Framework
在.net 4.0中,引入了一个新的类CancellationToken,这个类基本上集成了我们各种常用的取消方式,在并发任务中非常有用. 同步模式下的取消: 一种比较常见的需要支持取消功能的的是一些 ...
- .NET4.0并行计算技术基础(8)
说明: 要想看懂本系列文章,需要您对.NET多线程开发有基本的了解.我在新书<面向对象的艺术 --.NET Framework 4.0技术剖析与应用>(暂名)中花了近200页的篇幅来介绍. ...
- 多线程编程学习笔记——任务并行库(二)
接上文 多线程编程学习笔记--任务并行库(一) 三. 组合任务 本示例是学习如何设置相互依赖的任务.我们学习如何创建一个任务的子任务,这个子任务必须在父任务执行结束之后,再执行. 1,示例代码如下 ...
- 多线程编程学习笔记——任务并行库(三)
接上文 多线程编程学习笔记--任务并行库(一) 接上文 多线程编程学习笔记--任务并行库(二) 六. 实现取消选项 本示例学习如何实现基于Task的异步操作进行取消流程,以及在任务真正运行前如何知 ...
- C#多线程开发-任务并行库
你好,我是阿辉. 正文共2090字,预计阅读时间:6min. 之前学习了线程池,知道了它有很多好处. 使用线程池可以使我们在减少并行度花销时节省操作系统资源.可认为线程池是一个抽象层,其向程序员隐藏了 ...
- 三分钟总览微软任务并行库TPL
点击上方蓝字进行关注 有小伙伴问我每天忽悠的TPL是什么? ☹️ 这次站位高一点,严肃讲一讲. 引言 俗话说,不想开飞机的程序员不是一名好爸爸:作为微软技术栈的老鸟,一直将代码整洁之道奉为经典, 优秀 ...
- .NET异步程序设计之任务并行库
目录 1.简介 2.Parallel类 2.0 Parallel类简介 2.1 Parallel.For() 2.2 Parallel.ForEach() 2.3 Parallel.Invoke() ...
最新文章
- python代码大全o-Python简单I/O操作示例
- java中ssh如何理解
- c# 学习笔记 (1) 类型转换
- 备战2020腾讯广告算法大赛:(2017-2019比赛开源和数据等)
- CentOS 关闭、启动网卡
- PHP Collection 类
- 史上最详细 纯CSS打造3D文本滚动
- c语言值传递 地址传递 引用传递参数,C++参数传递(值传递,引用传递)
- python绘图函数m_Python散点图。m的尺寸和样式
- Keras框架:人脸检测-mtcnn思想及代码
- ASP.Net防止页面刷新重复提交
- 小程序 | 保存图片时处理名称的细节(时间戳+后缀名)
- PHP基础知识之文件加载
- mysql mha好吗_MySQL高可用方案MHA的一些总结和思考
- 牛掰!某厂风控大佬整理的一套黑客学习思维导图及教程!
- ss客户端以及tcp,udp,dns代理ss-tproxy本地安装版--centos7.3 x64以上(7.3-7.6x64测试通过)...
- 最新国产操作系统uos一小时使用体验
- Cepton宣布与美国底特律顶级汽车制造商合作,赢得业内最大ADAS激光雷达量产订单
- Ubuntu 14.04出现“device not managed”错误及ubuntu可以ping通外网浏览器上不了网。
- (比较器)Comparator比较器
热门文章
- [PTA]L2-001 紧急救援 (25 分)
- 简易OA漫谈之工作流设计(四,怎么支持会签)
- WCF、WebAPI、WCFREST、WebService之间的区别
- Velocity 页面加减运算
- lua IDE all
- JAVA学习笔记-“Hello World”
- Nodejs读写文件
- 无法解决 equal to 运算中 Chinese_PRC_CI_AS 和 SQL_Latin1_General_CP1_CI_AS 之间的排序规则冲突。...
- 关于mobile中datagrid的使用
- mysql 中模糊查询的四种用法介绍