【憩园】C#并发编程之概述
写在前面
并发编程一直都存在,只不过过去的很长时间里,比较难以实现,随着互联网的发展,人口红利的释放,更加友好的支持并发编程已经成了主流编程语言的标配,而对于软件开发人员来说,没有玩过并发编程都会有点不好意思。本系列文章将会以C#语言为主,详细介绍并发编程。
什么是并发编程,其实很简单,并发编程就是在一台处理器上同时做多件事情,并发编程的目标就是充分利用处理器的每一个核,以达到最高的处理性能。举个例子,服务器在响应第一个请求的同时响应第二个请求。
并发编程的方向
多线程
线程是一个独立的运行单元,是操作系统中能够进行运算调度的最小单位,它包含于进程之中,是进程中的实际运行单位。每个线程都有自己独立的栈,但是与进程内的其他线程共享内存。现在的.NET程序都维护了一个线程池,里面有着一定数量的工作线程,这些线程等待着执行分配下来的任务,线程池也可以随时监测线程的数量,以备开发者根据业务情况灵活处理。多线程也是我们并发编程的技术基础。
并行编程
并行编程主要用于分解计算密集型的任务片段,并将其分配给多个线程。前提是,程序中的任务可以分割成多个相互独立的任务块,关键字是相互独立,如果依赖太大,就不适合用并行编程。
并行编程利用CPU的空闲资源,充分提高了CPU的利用率,提高了系统的吞吐量。在大多数情况下,服务器本身就已经具备了并行处理能力,当通过编程进行并行处理的时候,需要慎重,因为使用不当将会导致内存溢出等风险,同时也会因为占用服务器资源而导致服务器本身的并行处理能力显著下降,严重的时候回导致系统无法使用。所以在进行编程的时候,尽量不要处理过长或者过短的任务。
并行处理分为数据并行和任务并行,其实他们都使用到了动态调整的分割算法,在任务分割后分配给工作线程。可以通过以下两种方式实现并行编程,一种是Parallel.ForEach以及更加优美的PLINQ,这是并行编程的推荐处理方式,并且它们自带自动分配任务的算法,可以在运行时进行调整;
在编写并行任务的时候,需要注意的是闭包所带来的风险。因为闭包捕获的是引用而不是值,所以可以在不经意间共享这些变量。一个比较好的处理就是,在使用闭包外的变量的时候,可以在闭包内定义局部变量,用以规避闭包带来的变量共享问题。
需要说明的是,线程池会根据需要增加线程数量,线程池采用的是工作窃取队列,以尽可能的达到高效
异步编程
目前最常用的异步编程模型是TAB编程(基于任务的编程模式)。异步编程提高了响应能力,也实现了可扩展性。比较直观的是,大家在处理Winform的时候遇到过界面卡死的情况,异步编程可以在程序运行的过程中继续相应用户的输入,而不会导致界面卡死,并提高了提高服务器端应用的TPS(Transactions Per Second)和 QPS (Queries Per Second)。
.NET4.5以后为异步编程引入了async和await关键字,async关键字加在方法声明上,主要用来配合方法内的await关键字,这两个关键字的引入,使得C#在异步编程上更加优雅。如下所示
1: public async Task DelayAsync()
2: {
3: await Task.Delay(1000);
4: }
异步编程的执行流程一般是,当系统运行至await,会暂停,并可以捕捉到当前的上线文,SynchronizationContext,如果该上线文为空,就会使用当前的TaskScheduler,该方法也会在这个上线文中继续执行。代码执行完以后,会尝试在原始的上下文中恢复运行。
注意:运行winform和asp.net请求时会采用UI上下文或者asp.net上下文,其他情况下则采用线程池上下文。
异步方法的等待方式有await,Task.Wait和Task<T>.Result。但是要避免是用Task.Wait和Task<T>.Result,因为他们在UI线程或者ASP.NET线程环境中会导致死锁。这个地方需要说明一下死锁问题
1: public async Task DelayAsync()
2: {
3: await Task.Delay(1000);//捕捉当前上下文,并试图在已捕捉的上下文中继续运行
4: }
5:
6: void Test()
7: {
8: Task task= DelayAsync();
9: Task.Wait();//同步程序块,正在等待异步方法完成=======阻塞线程
10: }
UI或者asp.net的上下文每次只能同时运行一个线程。Wait方法已经阻塞了一个线程,所以在await的时候无法捕捉上下文。可以使用ConfigureAwait方法,设置参数continueOnCapturedContext为false。由此,可以带来一个启示,就是在线程池线程上使用ConfigureAwait(false),在用户界面或接口代码中再恢复过来。
异步编程中有一条重要的准则就是,当你使用了异步编程的时候,最好一直使用,也是为了防止死锁。
优化使用:
避免上下文延续,延续任务过多会导致性能问题
如果一个async方法一个需要用到上下文一个不需要用到,可以考虑拆分为两个async方法,这样代码组织也会更直观。
写到最后
以上只是提出了C#并发编程的引子,后面将会详细介绍C#并发编程的知识点。当然,C#并发编程还有其他内容,比如响应式编程和TPL数据流这些,我平时用的比较少,所以此处没有再做介绍,有兴趣的同学可以另外查看一下。
【憩园】C#并发编程之概述的更多相关文章
- [C#] 《Concurrency in C# Cookbook》读书笔记(一)- 并发编程概述
并发编程概述 前言 我们经常在耳边听说一些关于高性能.并发和并行等名词,并且很多人都对并发编程有一些误解. 误解 1:并发就是多线程? 答:多线程只不过是并发编程的其中一种形式而已.并发编程的种类很多 ...
- 并发编程概述--C#并发编程经典实例
优秀软件的一个关键特征就是具有并发性.过去的几十年,我们可以进行并发编程,但是难度很大.以前,并发性软件的编写.调试和维护都很难,这导致很多开发人员为图省事放弃了并发编程.新版.NET 中的程序库和语 ...
- 并发编程概述 委托(delegate) 事件(event) .net core 2.0 event bus 一个简单的基于内存事件总线实现 .net core 基于NPOI 的excel导出类,支持自定义导出哪些字段 基于Ace Admin 的菜单栏实现 第五节:SignalR大杂烩(与MVC融合、全局的几个配置、跨域的应用、C/S程序充当Client和Server)
并发编程概述 前言 说实话,在我软件开发的头两年几乎不考虑并发编程,请求与响应把业务逻辑尽快完成一个星期的任务能两天完成绝不拖三天(剩下时间各种浪),根本不会考虑性能问题(能接受范围内).但随着工 ...
- Python并发编程-并发解决方案概述
Python并发编程-并发解决方案概述 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.并发和并行区别 1>.并行(parallel) 同时做某些事,可以互不干扰的同一个时 ...
- C#并发编程实例讲解-概述(01)
在工作中经常遇到需要并发编程的实例,一直没有时间来整理,现在空了下来,个人整理对并发一下理解. 关于并发编程的几个误解 误解一:并发编程就是多线程 实际上多线只是并发编程的一中形式,在C#中还有很多更 ...
- 《C#并发编程经典实例》学习笔记-第一章并发编程概述
并发编程的术语 并发 同时做多件事情 多线程 并发的一种形式,它采用多个线程来执行程序. 多线程是并发的一种形式,但不是唯一的形式. 并行处理 把正在执行的大量的任务分割成小块,分配给多个同时运行的线 ...
- C#并发编程-1 并发编程概述
一 并发编程简介 1.1 关于并发和并行 并发和并行的概念: 并发:(Concurrent),在某个时间段内,如果有多个任务执行,即有多个线程在操作时,如果系统只有一个CPU,则不能真正同时进行一个以 ...
- Atitit.并发编程原理与概论 attilax总结
Atitit.并发编程原理与概论 attilax总结 1. 并发一般涉及如下几个方面:2 2. 线程安全性 ( 2.2 原子性 2.3 加锁机制2 2.1. 线程封闭3.3.1Ad-hoc线程封闭 3 ...
- [书籍]用UWP复习《C#并发编程经典实例》
1. 简介 C#并发编程经典实例 是一本关于使用C#进行并发编程的入门参考书,使用"问题-解决方案-讨论"的模式讲解了以下这些概念: 面向异步编程的async和await 使用TP ...
随机推荐
- php一些高级函数方法
PHP高级函数 1.call_user_func (http://php.net/manual/zh/function.call-user-func.php) 2.get_class (http:// ...
- 2018年10月OKR初步规划
OKR(Objectives and Key Results)即目标+关键结果,是一套明确和跟踪目标及其完成情况的管理工具和方法 今天是十月的第一个工作日,也是我归零的第一天,受到一位前辈的启发,我决 ...
- Bootstrap 常用属性
一,关于按钮 btn系列 二.关于div 移动位置 col 系列 col-md 系列 col-lg系列 这些都是让多个div在当前页面等大小 三.居中系列 1.文本居中 text-center 2.图 ...
- 十八、泛型 l 注解 l Servlet3.0 l 动态代理 l 类加载器基础加强
l 泛型 l 注解 l Servlet3.0 l 动态代理 l 类加载器 泛型 1 回顾泛型类 泛型类:具有一个或多个泛型变量的类被称之为泛型类. public class A<T> { ...
- 微信小程序开发-tabbar组件
"tabBar": { "backgroundColor": "#303133", "color": "#ff ...
- Vs 开发时无法断点问题
1.清除解决方案 2.重新编译 3.删除项目目录下的obj 和 bin 4.在vs中配置 工具--项目--调试--去除勾选 要求源文件与原始版本完全匹配 关于调试问题 1.关闭诊断工具, 工具 =&g ...
- LeetCode编程训练 - 位运算(Bit Manipulation)
位运算基础 说到与(&).或(|).非(~).异或(^).位移等位运算,就得说到位运算的各种奇淫巧技,下面分运算符说明. 1. 与(&) 计算式 a&b,a.b各位中同为 1 ...
- 多媒体文件格式(四):TS 格式
一.TS 格式标准介绍 TS是一种音视频封装格式,全称为MPEG2-TS.其中TS即"Transport Stream"的缩写. 先简要介绍一下什么是MPEG2-TS: DVD的音 ...
- IntelliJ IDEA 使用 Git 并将 GitHub 作为远程代码仓库
安装本地Git 官方下载地址:http://git-scm.com/downloads 不过这个地址一般下不动,我们可以选择在腾讯软件中心下载,速度很快. 腾讯软件中心的下载地址:https://pc ...
- [Swift]LeetCode869. 重新排序得到 2 的幂 | Reordered Power of 2
Starting with a positive integer N, we reorder the digits in any order (including the original order ...