菜鸟学习并行编程,参考《C#并行编程高级教程.PDF》,如有错误,欢迎指正。

目录

  • C#并行编程-相关概念

  • C#并行编程-Parallel

  • C#并行编程-Task

  • C#并行编程-并发集合

  • C#并行编程-线程同步原语

  • C#并行编程-PLINQ:声明式数据并行

背景

基于任务的程序设计、命令式数据并行和任务并行都要求能够支持并发更新的数组、列表和集合。

在.NET Framework 4 以前,为了让共享的数组、列表和集合能够被多个线程更新,需要添加复杂的代码来同步这些更新操作。

如您需要编写一个并行循环,这个循环以无序的方式向一个共享集合中添加元素,那么必须加入一个同步机制来保证这是一个线程安全的集合。

System.Collenctions和System.Collenctions.Generic 名称空间中所提供的经典列表、集合和数组的线程都不是安全的,不能接受并发请求,因此需要对相应的操作方法执行串行化。

下面看代码,代码中并没有实现线程安全和串行化:

 View Code

代码中开启了三个并发操作,每个操作都向集合中添加1000条数据,在没有保障线程安全和串行化的运行下,实际得到的数据并没有3000条,结果如下:

为此我们需要采用Lock关键字,来确保每次只有一个线程来访问  _Products.Add(product); 这个方法,代码如下:

    class Program{private static object o = new object();private static List<Product> _Products { get; set; }/*  coder:释迦苦僧  *  代码中 创建三个并发线程 来操作_Products 集合*  System.Collections.Generic.List 这个列表在多个线程访问下,不能保证是安全的线程,所以不能接受并发的请求,我们必须对ADD方法的执行进行串行化*/static void Main(string[] args){_Products = new List<Product>();/*创建任务 t1  t1 执行 数据集合添加操作*/Task t1 = Task.Factory.StartNew(() =>{AddProducts();});/*创建任务 t2  t2 执行 数据集合添加操作*/Task t2 = Task.Factory.StartNew(() =>{AddProducts();});/*创建任务 t3  t3 执行 数据集合添加操作*/Task t3 = Task.Factory.StartNew(() =>{AddProducts();});Task.WaitAll(t1, t2, t3);Console.WriteLine("当前数据量为:" + _Products.Count);Console.ReadLine();}/*执行集合数据添加操作*/static void AddProducts(){Parallel.For(0, 1000, (i) =>{Product product = new Product();product.Name = "name" + i;product.Category = "Category" + i;product.SellPrice = i;lock (o){_Products.Add(product);}});}}class Product{public string Name { get; set; }public string Category { get; set; }public int SellPrice { get; set; }}

但是锁的引入,带来了一定的开销和性能的损耗,并降低了程序的扩展性,在并发编程中显然不适用。

System.Collections.Concurrent

.NET Framework 4提供了新的线程安全和扩展的并发集合,它们能够解决潜在的死锁问题和竞争条件问题,因此在很多复杂的情形下它们能够使得并行代码更容易编写,这些集合尽可能减少需要使用锁的次数,从而使得在大部分情形下能够优化为最佳性能,不会产生不必要的同步开销。

需要注意的是:

线程安全并不是没有代价的,比起System.Collenctions和System.Collenctions.Generic命名空间中的列表、集合和数组来说,并发集合会有更大的开销。因此,应该只在需要从多个任务中并发访问集合的时候才使用并发几个,在串行代码中使用并发集合是没有意义的,因为它们会增加无谓的开销。

为此,在.NET Framework中提供了System.Collections.Concurrent新的命名空间可以访问用于解决线程安全问题,通过这个命名空间能访问以下为并发做好了准备的集合。

1.BlockingCollection 与经典的阻塞队列数据结构类似,能够适用于多个任务添加和删除数据,提供阻塞和限界能力。

2.ConcurrentBag 提供对象的线程安全的无序集合

3.ConcurrentDictionary  提供可有多个线程同时访问的键值对的线程安全集合

4.ConcurrentQueue   提供线程安全的先进先出集合

5.ConcurrentStack   提供线程安全的后进先出集合

这些集合通过使用比较并交换和内存屏障等技术,避免使用典型的互斥重量级的锁,从而保证线程安全和性能。

ConcurrentQueue 

ConcurrentQueue 是完全无锁的,能够支持并发的添加元素,先进先出。下面贴代码,详解见注释:

 View Code

需要注意的是,代码中的输出时间并不能够完全正确的展示出并发代码下的ConcurrentQueue性能,采用ConcurrentQueue在一定程度上也带来了损耗,如下图所示:

ConcurrentQueue 还有另外两种方法:TryDequeue  尝试移除并返回 和 TryPeek 尝试返回但不移除,下面贴代码:

 View Code

需要注意 TryDequeue  和  TryPeek 的无序性,在多线程下

ConcurrentStack  是完全无锁的,能够支持并发的添加元素,后进先出。下面贴代码,详解见注释:

 View Code

ConcurrentStack 还有另外两种方法:TryPop 尝试移除并返回 和 TryPeek 尝试返回但不移除,下面贴代码:

 View Code

对于并发下的其他集合,我这边就不做代码案列了,大家可以通过下面的链接查看,如有问题,欢迎指正

http://msdn.microsoft.com/zh-cn/library/system.collections.concurrent(v=vs.110).aspx

作者:释迦苦僧 出处:http://www.cnblogs.com/woxpp/p/3935557.html
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。

C#并行编程-并发集合相关推荐

  1. dnet 并行编程学习总结

    .Net并行编程高级教程--Parallel http://www.cnblogs.com/stoneniqiu/p/4857021.html 一直觉得自己对并发了解不够深入,特别是看了<代码整 ...

  2. python网络编程基础(线程与进程、并行与并发、同步与异步、阻塞与非阻塞、CPU密集型与IO密集型)...

    python网络编程基础(线程与进程.并行与并发.同步与异步.阻塞与非阻塞.CPU密集型与IO密集型) 目录 线程与进程并行与并发同步与异步阻塞与非阻塞CPU密集型与IO密集型 线程与进程 进程 前言 ...

  3. 多线程编程学习笔记——使用并发集合(三)

    接上文 多线程编程学习笔记--使用并发集合(一) 接上文 多线程编程学习笔记--使用并发集合(二) 四.   使用ConcurrentBag创建一个可扩展的爬虫 本示例在多个独立的即可生产任务又可消费 ...

  4. 《Haskell并行与并发编程》——第2章,第2.1节惰性求值和弱首范式

    本节书摘来自异步社区<Haskell并行与并发编程>一书中的第2章,第2.1节惰性求值和弱首范式,作者[英]Simon Marlow,更多章节内容可以访问云栖社区"异步社区&qu ...

  5. C#并发编程之初识并行编程

    写在前面 之前微信公众号里有一位叫sara的朋友建议我写一下Parallel的相关内容,因为手中商城的重构工作量较大,一时之间无法抽出时间.近日,这套系统已有阶段性成果,所以准备写一下Parallel ...

  6. Java7并发编程指南——第六章:并发集合

    Java7并发编程指南--第六章:并发集合 @(并发和IO流) Java7并发编程指南第六章并发集合 思维导图 项目代码 思维导图 项目代码 GitHub:Java7ConcurrencyCookbo ...

  7. c语言多核编程,多核并行计算——并发与并行编程问题

    并发是用来描述并行执行的方式(看上去一起发生的事件,例如目前操作系统的多任务调度程序,看上去桌面上有许多程序在同时运行.),并发是形容词. 并行是指通过并发将一个操作分解成一组粒度更细的工作单元,并且 ...

  8. Java并发编程:进程、线程、并行与并发

    一谈到Java并发编程,我们一般就会联想起进程.线程.并行.并发等等概念.那么这些概念都代表什么呢?进程与线程有什么关系?并发与并行又是什么关系呢? 01 进程与线程 进程是指程序的一次动态执行过程, ...

  9. Java并发编程之——并发集合

    并发集合是原有集合框架的补充,为多线程并发程序提供了支持.主要有:BlockingQueue,ConcurrentMap,ConcurrentNavigableMap三个接口. 新的java.util ...

最新文章

  1. I.MX6 android 源码下载
  2. android 时钟进度条,CSS3时钟式进度条
  3. 深蓝学院《从零开始手写VIO》作业五
  4. eclipse代码补全
  5. SliceProceduralMesh的使用
  6. Kafka将逐步弃用对zookeeper的依赖
  7. solaris10默认防火墙软件ipfilter
  8. ref:PHP反序列化漏洞成因及漏洞挖掘技巧与案例
  9. Vue.use 写多个_西双版纳能写立项报告收费公司
  10. exploration 和 exploitation 的区别
  11. IMM将软件测试成熟度分为5个,软件测试成熟度模型
  12. Java多线程实现多用户与服务端Socket通信
  13. window 服务器443端口占用,443和80端口被占用win10如何解决_443和80端口被占用win10怎么处理...
  14. 一位基金经理13年的期货感悟
  15. idea项目名称重命名
  16. 请教:关于爬取歌词的一点疑惑
  17. matlab快速入门(1):输入命令
  18. Oracle怎么安装
  19. Cursor:GPT-4 免费的强大代码编辑器
  20. python生成的word表格设置内容居中

热门文章

  1. java map取第一个元素_Java 8从Map中的匹配值中提取第一个键
  2. 《深入理解计算机系统》(2) 信息的表示和处理
  3. 周记php,工作周记 | php外包与php技术服务商
  4. 全新玖五社区系统整站源码
  5. 使用C#登录带验证码的网站
  6. 关于大型网站技术演进的思考(三)--存储的瓶颈(3)
  7. JS判断浏览器是否支持某一个CSS3属性
  8. magento 添加facebook like 和google +1 按钮
  9. PHP中register_globals参数为OFF和ON的区别
  10. JavaScript、php 获得 YouTube 视频缩略图和标题