一、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#提供的这张表

最新文章

  1. PHP中面相对象对象的知识点整理
  2. C#之线程和并发
  3. U-boot mkimage指定Linux内核地址时的两种方式
  4. ZOJ 3469 Food Delivery 区间DP
  5. HDU 2517 棋盘分割
  6. 经典SQL语句大全之数据开发
  7. tar、scp、sftp、rsync简单使用
  8. VT控制码
  9. Web后端 JAVA实现验证码生成与验证功能
  10. form组件+cookie+session总结
  11. windos下安装pgAdmin
  12. 那些年,很多人没看懂的Python内置函数
  13. 普通程序员转型AI免费教程整合,零基础也可自学
  14. python中的open( )函数
  15. Java并发包中CyclicBarrier的源码分析和使用
  16. spring PROPAGATION
  17. 带你走进Linux(Ubuntu)
  18. 深入研究java.lang.Process类
  19. Same Tree leetcode java
  20. C语言的乱七八糟

热门文章

  1. Arria10收发器校正
  2. 如何使用vs进行代码比较
  3. hibernate映射组成关系
  4. #微码分享#C++变参字符串格式化函数format_string
  5. 20170831工作日记--自定义View学习
  6. python基于pillow库的简单图像处理
  7. noip第12课资料
  8. 谷歌的java文本差异对比工具
  9. JAVA本地读取文件,解决中文乱码问题
  10. 认识Hadoop