第二十六章 线程基础

目录:

26.1 Windows为什么要支持线程

26.2 线程开销

26.3 停止疯狂

26.4 CPU发展趋势

26.5 CLR线程和Windows线程

26.6 使用专用线程执行异步的计算限制操作

26.7 使用线程的理由

26.8 线程调度和优先级

26.9 前台线程和后台线程

26.10 继续学习

Windows为什么要支持线程

作为一个Windows概念,线程的职责是对CPU进行虚拟化。Windows为每个进程都提供了改进程专用的线程(功能相当于一个CPU)。应用程序的代码进入死循环,与那个代码关联的进程回“冻结”,但其他进程不会冻结,会继续执行。

线程开销

线程允许用户强制终止似乎已冻结的应用程序。和一切虚拟化机制一样,线程有空间(内存耗用)和时间(运行时的执行性能)上的开销。

线程内核对象:OS为系统中创建的每个线程都分配并初始化这种数据结构之一。数据结构包含一组对线程进行描述的属性。数据结构还包含所谓的线程上下文。上下文是包含CPU寄存器集合的内存块。

线程环境块(TEB):TEB是在用户模式(应用程序代码能快速访问的地址空间)中分配和初始化的内存块。TEB耗用1个内存页。TEB包含线程的异常处理链首。线程进入的每个try块都在链首插入一个节点;线程退出try块时从链中删除改节点。TEB还包含线程的“线程本地存储”数据,以及由GDI和OpenGL图形使用的一些数据结构。

用户模式栈:用户模式栈存储传给方法的局部变量和实参。它包含一个地址;指出当前方法返回时,线程应该从什么地方接着执行。

内核模式栈:应用程序代码向操作系统中的内核模式函数传递实参时,还会使用内核模式栈。

DLL线程连接(attach)和线程分离(detach)通知:Windwos的一个策略是,任何时候在进程中创建线程,都会第哦啊用进程中加载的所有非托管DLL的DllMain方法,并向该方法传递DLL_THREAD_ATTACH标志。任何线程终止,都会调用进程中的所有非托管DLL的DllMain方方法,并向方法传递DLL_THREAD_DETACH标志。

Windows任何时刻只将一个线程分配给一个CPU。那个线程能运行一个“时间片(也称为“量”或“量程”)”的长度。时间片到期,Windows就上下文切换到另一个线程:

1.将CPU寄存器的值保存到当前正在运行的线程的内核对象内部的一个上下文结构中。

2.从现有线程集合中选出一个线程供调度。如果该线程由另一个进程拥有,Windows在开始执行任何代码或者接触任何数据之前,还必须切换CPU“看见”的虚拟地址空间。

3.将所选上下文结构中的值加载到CPU的寄存器中。

上下文切换时净开销;所产生的开销不会换来任何内存或性能上的收益。所以说上下文切换时通过牺牲性能来换取更好的用户体验。

执行上下文切换所需的时间取决于CPU架构和速度。而填充CPU缓存所需要的时间取决于系统中运行的应用程序,CPU缓存的大小以及其他各种因素。

执行垃圾回收时,CLR必须挂起(暂停)所有线程,遍历它们的栈来查找根以便对堆中的对象进行标记,再次遍历它们的栈,在恢复所有线程。

停止疯狂

CPU发展趋势

多个CPU

超线程芯片

多核芯片

CLR线程和Windows线程

CLR使用Windows的线程处理功能,CLR线程完全等价于Windows线程。

使用专用线程执行异步的计算限制操作

满足以下条件就可以创建自己的线程:

线程需要以非普通线程优先级运行。

需要线程表现为要给前台线程,防止应用程序在线程结束任务前终止。

计算限制的任务需要长时间运行。

要启动线程,并可能调用Thread的Abort方法来提前终止它。

使用线程的理由

 可响应性(通常是对于客户端GUI应用程序)

Windows为每个进程提供它自己的线程,确保发生死循环的应用程序不会妨碍其他应用程序。

性能(对于客户端和服务器应用程序)

由于Windows每个CPU调度一个线程,而且多个CPU能并发执行这些线程,所以同时执行多个操作能提升性能。

线程调度和优先级

抢占式操作系统必须使用算法判断在什么时候调度哪些线程多长时间——线程可在任何时间停止(被抢占)并调度另一个线程。(每个线程的内核对象包含一个上下文结构,上下文结构反映了线程上一次执行完毕后CPU寄存器的状态。在一个时间片之后,Windows检查现存的所有线程内核对象。在这些对象中,只有那些没有正在等待什么的线程才适合调度。Windows选择一个可调度的线程内核对象,并上下文切换到它。Windows实际记录了每个线程被上下文切换到的次数。然后,线程开始执行代码,并在其进程的地址空间处理数据。又过过了一个时间片之后,Windows执行下一次上下文切换。Windows从系统启动开始便一直执行上下文切换,直到系统关闭为止。)

每个线程都分配了从0到31的优先级。饥饿:较高优先级的线程占用了太多CPU时间,造成较低优先级的线程无法运行。

系统启动时会创建一个特殊的零页线程,该线程的优先级是0,而且是整个系统唯一优先级为0的线程。在没有其他线程需要“干活儿”的时候,零页线程将系统RAM的所有空闲页清零。

进程优先级类:Idle,Below Normal,Above Normal,High,Realtime.

相对线程优先级:Idle,Lowest,Below Normal,Normal,Above Normal,Highest,Time-Critical.

相对线程优先级 进程优先级类
Idle Below Normal Normal Above Nomal High Realtime
Time-Critical 15 15 15 15 15 31
Highest 6 8 10 12 15 26
Above Normal 5 7 9 11 14 25
Normal 4 6 8 10 13 24
Below Normal 3 5 7 9 12 23
Lowest 2 4 3 8 11 22
Idle 1 1 1 1 1 16

前台线程和后台线程

CLR将每个线程要么视为前台线程,要么视为后台线程。一个进程的所有前台线程停止运行时,CLR强制终止仍在运行的任何后台线程。这些后台线程被直接终止,不抛出异常。

应用程序的主线程以及通过构造一个Thread对象来显式创建的任何线程都默认为前台线程,线程池线程默认为后台线程。由进入托管执行环境的本机代码创建的任何线程被标记为后台线程

原文地址:https://www.cnblogs.com/terry-1/p/10683083.html

时间: 2024-10-12 14:49:09

第二十六章 线程基础的相关文章

“全栈2019”Java多线程第二十六章:同步方法生产者与消费者线程

难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多线程第二十六章:同步方法生产者与消费者线程 下一章 "全栈2019"Java多线程第二十七章:Lock获取lock/释放unlock锁 学习小组 加入同步学习小组,共同交流与进步. 方式一:关注头条号Gorhaf,私信"Java学习小组". 方式二:关注公众号Gorha

【WPF学习】第三十六章 样式基础

原文:[WPF学习]第三十六章 样式基础 前面三章介绍了WPF资源系统,使用资源可在一个地方定义对象而在整个标记中重用他们.尽管可使用资源存储各种对象,但使用资源最常见的原因之一是通过他们的保存样式. 样式是可应用于元素的属性值集合.WPF样式系统与HTML标记中的层叠样式表(Cascading Style Sheet,CSS)标准担当类似的角色.与CSS类似,通过WPF样式可定义通用的格式化特性集合,并且为了保证一致性,在整个应用程序中应用他们.与CSS一样,WPF样式也能够自动工作,指定具体

【WPF学习】第二十六章 Application类——应用程序的生命周期

原文:[WPF学习]第二十六章 Application类--应用程序的生命周期 在WPF中,应用程序会经历简单的生命周期.在应用程序启动后,将立即创建应用程序对象,在应用程序运行时触发各种应用程序事件,你可以选择监视其中的某些事件.最后,当释放应用程序对象时,应用程序将结束. 一.创建Application对象 使用Application类的最简单方式是手动创建它.下面的示例演示了最小的程序:在应用程序入口(Main()方法)处创建名为MainWindow的窗口,并启动一个新的应用程序: 在本质

Windows核心编程读书笔记-第六章线程基础

1.相较于线程,进程所使用的系统资源更多.其原因在于地址空间.为一个进程创建一个虚拟的地址空间需要大量系统资源.线程只有一个内核对象和一个栈. 2.线程的入口函数 DWORD WINAPI ThreadFunc(PVOID pvParam){ DWORD dwResult = 0; ... return(dwResult); } 线程函数的几点说明 线程函数可以任意命名. 线程函数只有一个参数,而其意义由我们(而非操作系统)来定义.因此,我们不必担心ANSI/Unicode问题. 线程函数必须返

《Python 学习手册4th》 第十六章 函数基础

''' 时间: 9月5日 - 9月30日 要求: 1. 书本内容总结归纳,整理在博客园笔记上传 2. 完成所有课后习题 注:“#” 后加的是备注内容 (每天看42页内容,可以保证月底看完此书) “重点笔记”“本章习题” - 标题1,二级标题用- 标题2,笔记大纲标题.习题题目- 加粗,16px ''' 重点笔记 摘要 函数是Python为了代码最大程度的重用和最小化代码冗余而提供的最基本的程序结构.一. 为何使用函数 最大化的代码重用和最小化代码冗余 流程的分解 本章习题: 1. 编写函数有什么

奋斗吧,程序员——第二十六章 赌书消得泼茶香, 当时只道是寻常

严格意义上的产品经理,职责是更为全面的: -根据公司和产品发展策略,负责产品策划管理工作,提升用户体验: -负责编写产品需求书产品原型,协助开发团队理解和掌握需求,对产品需求方向和易用性负责: -负责相关产品开发项目周期和进度把控,确保对产品开发至最终上线运营,对进度质量负责: -负责跨部门协调和沟通,推动开发.测试.运营等人员紧密合作达成产品目标: -协调产品上线前的产品文档整理,商务推广,市场宣传等配合工作: -对用户需求.市场需求和业务需求进行调研分析,不断优化产品,提升产品质量,提高用户

C++程序设计原理与实践 第二十六章部分答案

1 bool fn(vector<int>::iterator vi1,vector<int>::iterator vi2,int i) 2 { 3 vector<int>::iterator vi3=vi2-1; 4 if(vi1>vi3) 5 return 0; 6 else 7 { 8 vector<int>::iterator vi=vi1+(vi2-vi1)/2; 9 if(*vi==i) 10 return 1; 11 else if(*v

第十六章 函数基础

#1. #A:python的def语句实际上是一个可执行语句,当他运行的时候,它创建一个新的函数对象并将其赋值给一个变量名 #B:因为def语句是一个语句,所以一个def可以出现在任一语句可以出现的地方,比如说嵌套在其他的语句中 #C:函数除了调用以外,还允许任意的属性附加到记录信息,以供使用 def FunA(Value): if Value: def FunB() : return 10 else: def FunB() : return 20 return 10 + FunB() b0 =

第二十六讲:基础一开放封闭原则

做出来的软件具有很强的扩展性,扩展并不是修改以前的源代码,而是在以前的代码之外添加新的功能. 重点是对扩展开放,对修改关闭. 银行业务员下有很多子类:负责存款的银行业务员,负责取款的银行业务员,负责转账的银行业务员.