C# 多线程学习系列一
一、Windows线程的由来 关于操作系统的一些知识
(1)、单个"工作线程"的问题
早期的Windows没有线程的概念,整个系统只有一个"工作线程",上面同时跑着操作系统代码和应用程序代码.这种方式最大的缺点就是,一个应用程序运行时会霸占整台机器(应为只有一个工作线程),且当它发生死循环时,会造成PC停止工作.如果此时重启,更shit的是,所有的应用程序都会停止,且丢失数据.
(2)、Windows进程
i、什么是Windows进程,以及它解决的问题
MS为了解决单个"工作线程"的问题,设计了新的内核,该内核实现了Windows进程的功能,每个Windows进程(应用程序要使用的资源集合)运行一个应用程序,如下图:
一个Chrome浏览器进程包含了很多子进程(子进程可以共享父进程的资源),后面包含了正在使用的资源集合,包括CPU、内存等.每个进程都有一个虚拟空间地址(PID).
当一个应用程序应为代码故障发生卡死等问题,并不会影响其他的应用程序的运行,只需要打开任务管理器,将该进程关闭即可.其他应用程序的数据也不会丢失,因为它们是彼此独立的进程.
ii、Window进程的安全性
在Windows中,进程之间不能相互访问(不包括父子进程),单个进程也无法访问Windows内核.
iii、关于CPU的问题
虽然Windows进程很好的解决了单个"工作线程"的问题,Windows不会发生一个应用程序崩溃,所有应用程序全都停止且所有运行着的应用程序的数据丢失的情况。但是如果PC只有一个CPU,当CPU本身发生死循环等问题,还是会导致PC停止工作.
iv、什么是Windows线程,以及Windows线程解决的问题
MS为了解决单个进程执行异常,导致CPU停止工作的问题,设计了Windows线程,它的作用是对CPU进行虚拟化,Windows会给每个Windows进程分配一个Windows线程,该线程相当于一个虚拟的CPU(包含CPU所有的功能),如果应用程序的代码进入死循环,相关进程会被停止,但是其他的应用程序进程并不会停止,会继续执行.因为它们拥有自己的线程(虚拟CPU).
2、Windows线程的消耗
虽然Windows线程保证了Windows的可靠性和健壮性,但是天下没有免费的午餐,随之带来的肯定是其他的PC资源消耗.这里不想介绍太多操作系统级别的东西,只说一些直观的我们能看到的.就以我的笔记本为例,打开任务管理器如下:
我的笔记本此时跑着176个进程,所以理论上至少有176个线程,但是实际却有2103个线程,平均每个进程12个线程.下面是我笔记本的配置
双核,理论上最优的配置是,只有两个线程,应为涉及到线程上下文切换(从一个线程上下文切换到另一个上下文),而上下文的切换的性能代价是十分大的.
我的CPU利用率为7%,说明93%的时间,这2103个线程啥事都没干,严重的浪费了我的内存.如果这个时候开启了远程桌面服务,假设10个用户连了我的笔记本,所有的开销会翻倍.
当然虽然线程的开销很大,但是相比于创建进程,开销相比较小.但是开发应用程序的时候,还是要合理的使用线程!
二、为什么要使用多线程
主要有两点,拿Windows来举例
(1)、Windows使用线程,每个线程拥有一个虚拟的CPU,包含CPU所有的功能,当一个应用程序使用的线程因为代码问题,发生故障时,Windows会关闭这个线程,但是这个线程使用的是虚拟的CPU,所以不会影响其他应用程序使用它们的线程,也就是虚拟CPU.所以线程保证了CPU的高可用.同时现在的电脑往往都有多个CPU,利用这个特性,我们可以使用代码创建多个线程,去执行不同的任务,比如一个Windows桌面程序,可以让主线程去处理用的输入,创建其他的线程去处理桌面程序的UI界面.这样用户体验就会非常好.不会说必须等到桌面UI全部初始化完,用户才能执行输入操作.
(2)、Windows每个CPU就能调度一个线程,如果你的PC有个多CPU,那么它们就能协同操作,同时也就是并发的执行多个任务.但是虽然线程能并发执行很多任务,但是如果创建的线程过多,理论上一个CPU只能调度一个线程,但是你创建的线程如果比CPU还多,那么windows就会进行上下文切换,这个性能损失是很可观的(不考虑创建线程本身的开销),所以关于线程创建的数量,还是需要慎重考虑.
三、关于CPU利用率
CPU利用率简单点说,就是CPU的使用效率,如果当PC长时间的响应I/O,或者在驱动硬件设备干活,而CPU本身却很空闲,这种情况CPU利用率就很低.
四、线程调度和优先级
1、线程调度
首先Windows是一个抢占式的操作系统,抢占式操作系统说白点就是线程的切换,因为大多数Windows操作系统运行了不止一个应用程序,而这些应用程序运行了不止一个线程,最后这些所有的线程加起来肯定超过PC的CPU核数(上面说了一个CPU只能调度一个线程),那么为了保证这些线程能尽可能的同时运行,所以Windows操作系统必须进行频繁的上下文切换,保证这些线程能同时调度.这也就是为什么你在Windows的操作系统同时开启多个应用程序会非常卡的原因.因为一下次有N多个线程同时开启,导致CPU工作压力飙升.
那么为什么说是抢占式的呢?因为每个内核包含一个上下文对象,这个对象包含了线程上次执行完毕的CPU寄存器状态,在一个CPU的时间片执行完毕之后(也就是一个线程执行完毕之后),Windows会便利所有的上下文,找出一个适合调度的上下文,并切换到这个上下文,执行该线程.这就是所谓的抢占式.Windows可以在任何时间抢占当前正在执行上下文,切换到下一个上下文,只要Windows觉得当前上下文更值得被调度。注:这是个很复杂的过程.所以你无法确保创建的线程会在什么时候被调度,以及调度多长时间.这些都由Windows来判断.说白点,它比你更聪明.并且他考虑的比你更全面.哈哈!
2、优先级
虽然你无法确定你的线程什么时候被调度,但是当你有一个线程这个线程执行非常重要的任务,但是Window内核本身并不能保证它的执行优先级,所以我们必须使用其他的手段来确保它能优先于其他线程的执行.万幸的是,Window也考虑到了这一点,设计了优先级这一概念,来满足我们的业务需求.
(1)、进程优先级
Windows支持6个进程优先级类,如下:
Idle(空闲),一般执行在操作系统空闲的时候执行的程序,比如Windows自动更新服务.屏幕保护程序等.
Below Normal(低于普通优先级)
Normal(普通优先级)
Above Normal(高于普通)
Hign(高)如果又非常关键的进程,可以使用.
Realtime(实时,超高优先级)不建议使用,会影响操作系统的进程,会造成"死机"的情况,使用这个优先级有权限要求(管理员有这个权限)
(2)、线程优先级
Windows为线程定义了0~31的优先级,Windows会优先调度高优先级的线程,注意,会存在线程抢占的情况,如果开启了一个应用程序,当该程序里面有一个31优先级的线程,那么Windows会挂起当前正在执行的低优先级的线程,给该线程使用.单核机器,如果存在过多的较高优先级的线程,那么低线程将不会被调度,这是种很shit的情况,所以要谨慎使用.
Windows提供了7个线程优先级
Idle(空闲)操作系统空闲时执行的线程
Lowest(最低级别)
Below Normal(低于正常)
Normal
Above Normal
Hignest
Time-Critical(实时)
(3)、关于进程优先级和线程优先级的联系
真实的线程优先级的大小取决于进程优先级,如果两个进程优先级一样,那么只看线程优先级大小.具体请看CLR via C#提供的这张表
C# 多线程学习系列一的更多相关文章
- .NET并行与多线程学习系列一
并行与多线程学习系列一 一.并行初试: public static void test() { ; i < ; i++) { Console.WriteLine(i); } } public s ...
- 多线程学习系列二(使用System.Threading)
一.什么是System.Threading.Thread?如何使用System.Threading.Thread进行异步操作 System.Threading.Thread:操作系统实现线程并提供各种 ...
- C# 多线程学习系列三之CLR线程池系列之ThreadPool
一.CLR线程池 1.进程和CLR的关系一个进程可以只包含一个CLR,也可以包含多个CLR2.CLR和AppDomain的关系一个CLR可以包含多个AppDomain3.CLR和线程池的关系一个CLR ...
- C# 多线程学习系列二
一.关于前台线程和后台线程 1.简介 CLR中线程分为两种类型,一种是前台线程.另一种是后台线程. 前台线程:应用程序的主线程.Thread构造的线程都默认为前台线程 后台线程:线程池线程都为后台线程 ...
- C# 多线程学习系列四之ThreadPool取消、超时子线程操作以及ManualResetEvent和AutoResetEvent信号量的使用
1.简介 虽然ThreadPool.Thread能开启子线程将一些任务交给子线程去承担,但是很多时候,因为某种原因,比如子线程发生异常.或者子线程的业务逻辑不符合我们的预期,那么这个时候我们必须关闭它 ...
- C#多线程学习(一) 多线程的相关概念(转)
什么是进程?当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源.而一个进程又是由多个线程所组成的. 什么是线程?线程是程序中的一个执行流,每个线程都有自己的专有寄 ...
- C#多线程学习(一) 多线程的相关概念
什么是进程?当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源.而一个进程又是由多个线程所组成的. 什么是线程?线程是程序中的一个执行流,每个线程都有自己的专有寄 ...
- [转载]C#多线程学习(一) 多线程的相关概念
原文地址:http://www.cnblogs.com/xugang/archive/2008/04/06/1138856.html 什么是进程?当一个程序开始运行时,它就是一个进程,进程包括运行中的 ...
- C#多线程学习(六) 互斥对象
如何控制好多个线程相互之间的联系,不产生冲突和重复,这需要用到互斥对象,即:System.Threading 命名空间中的 Mutex 类. 我们可以把Mutex看作一个出租车,乘客看作线程.乘客首先 ...
随机推荐
- Maven进行install的时候报错,COMPILATION ERROR : Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.13:test (default-test) on project cmu: There are test failures.
maven进行install的时候,test类里面报错: COMPILATION ERROR : [INFO] -------------------------------------------- ...
- sql计算经纬度得出最近距离的公式
sql计算经纬度得出最近距离的公式 //根据经纬度计算两点距离 mappoint //数据库已有字段,商家经纬度 实例:113.272148,23.147299 $lon = "" ...
- 实例讲解Silverlight 初始控件如何获得焦点
这个问题本来是在我实际的项目中遇到过的,但这其实是当初项目要求,要求一进入就要使得在用户名那个文字框中聚焦,而不是再用鼠标去点击获得焦点,后来自己费了点时间解决了.本来我没太注意就过去了,没想到在QQ ...
- 初识Android的ReactiveX
初识Android的ReactiveX 开发一个复杂一点的Android应用都会用到网络请求,交互和动画.这些都意味着 要写很多的回调嵌套.这样的代码也被称为callback hell(回调地狱).这 ...
- 一份不太简短的LaTeX模板
编译环境: Ubuntu16.04 texllive2016 sublime text3 + latextools 该模板使用与自己写文档,记笔记,记录代码,写作业等等. %!TEX program ...
- Forward团队-爬虫豆瓣top250项目-团队编程项目开发环境搭建过程
本次结对编程和团队项目我都需要用python环境,所以环境的搭建是一样的.(本文部分内容引用自己博客:http://www.cnblogs.com/xingyunqi/p/7527411.html) ...
- (动态规划)matrix -- hdu -- 5569
http://acm.hdu.edu.cn/showproblem.php?pid=5569 matrix Time Limit: 6000/3000 MS (Java/Others) Memo ...
- OC语言-block and delegate
参考博客 OC语言BLOCK和协议 iOS Block iOS Block循环引用精讲 iOS之轻松上手block 深入浅出Block的方方面面 Block apple官方参考 1.定义一个block ...
- hdu 5055
http://acm.hdu.edu.cn/showproblem.php?pid=5055 n个digit能组合出的最大无前导0奇数 无聊的模拟 #include <cstdio> #i ...
- python_列表、元组、字典、集合对比
列表.元组.字典.集合 列表.元组.字典.集合对比 比较项 列表 元组 字典 集合 类型名称 list tuple dict set 定界符 [] () {} {} 是否可变 是 否 是 是 是否有序 ...