[CLR via C#]25. 线程基础
一、Windows为什么要支持线程
- 线程内核对象(thread kernel object) OS为系统中创建的每个线程都分配并初始化这种数据结构。在该数据结构中,包含一组对线程进行描述的属性。 数据结构中还包含所谓的线程上下文(thead context)。上下文是一个内存块,其中包含了CPU的寄存器集合。Windows在一台x86CPU的计算机运行时,线程上下文使用约700字节的内存。对于x64和IA64CPU,上下文分别使用约1240字节和2500字节的内存。
- 线程环境块(thread environment block,TEB) TEB是在用户模式中分配和初始化的一个内存块。TEB耗用1个内存页(x86和x64CPU中是4KB,IA64CPU中是8K)。TEB包含线程的异常处理链首。线程进入的每个try块都在链首插入一个节点。线程退出try块时,会从链中删除该节点。除此之外,TEB还包括线程的"线程本地存储"数据,以及由GDI和OpenGL图形使用的一些数据结构。
- 用户模式栈(user-mode stack) 用户模式栈用于存储传给方法的局部变量和实参。它还包含一个地址:指向当前方法返回时,应该接着从哪个地址开始执行。默认情况下,Windows为每个线程的用户模式分配1MB的内存。
- 内核模式栈(kernel-model stack) 应用程序代码向OS中的一个内核模式的函数传递实参时,会使用内核模式栈。出于安全方面的原因,针对从用户模式的代码传给内核的任何实参,Windows都会把它们从线程的用户模式栈复制到线程的内核模式栈。一经复制,内核就可以验证实参的值,然后进行处理。除此之外,内核会调用它自己内部的方法,并利用内核模式栈传递自己的实参、存储函数的局部变量以及存储返回地址。在32为的Windows运行时,内核模式栈大小为12KB;在64位Windows上运行时,大小为24KB。
- DLL线程连接(attach)和线程分离(detach)通知 Windows的一个策略是,任何时候在进程中创建一个线程,都会调用那个进程中加载的所有DLL的DLLMain方法,并向该方法传递一个DLL_THREAD_ATTACH标识。类似的,任何时候一个线程终止,都会调用进程中的所有DLL的DLLMain方法,并向该方法传递一个DLL_THREAD_DETACH标识。有的DLL需要利用这些通知,为进程中创建和销毁的每个线程执行一些特殊的初始化或资源清理操作。
- 将CPU寄存器中的值保存到当前正在运行的线程的内核对象内部的一个上下文结构中。
- 从现有线程集合中选出一个线程供调度(这个就是要切换到的线程)。如果该线程由另一个进程拥有,Windows在开始执行任何代码或者任何数据之前,还必须切换CPU"看见"的虚拟地址空间。
- 将所选上下文结构中的值加载到CPU的寄存器中。
- 线程需要以非普通线程优先级运行。所有线程池线程都以普通优先级运行;虽然可以改变这种优先级,但不建议这样做。另外,在不同的线程池操作之间,对优先级的更改是无法持续的。
- 需要线程表现为一个前台线程,防止应用程序在线程结束它的任务之前终止。线程池的线程都是后台线程。如果CLR想要终止线程,它们可能被迫无法完成任务。
- 一个计算限制的任务需要长时间运行。线程池为了判断是否需要创建一个额外的线程,所采用的逻辑是比较复杂的。直接为长时间运行的任务创建一个专用线程,则可以避免这个问题。
- 要启动一个线程,并可能调用Thread的Abort方法来提前终止它。
public sealed class Thread : CriticalFinalizerobject,... {
public Thread(ParameterizedThreadStart start);
//这里没有列出不常用的构造器
}
start参数标识专用线程要执行的方法,这个方法必须和ParameterizedThreadStart委托的签名匹配。
delegate void ParameterizedThreadStart(Oject obj);
internal static class FirstThread {
public static void Go() {
Console.WriteLine("Main thread: starting a dedicated thread " +
"to do an asynchronous operation");
Thread dedicatedThread = new Thread(ComputeBoundOp);
dedicatedThread.Start(5); Console.WriteLine("Main thread: Doing other work here...");
Thread.Sleep(10000); // 模拟做其它工作(10 秒钟) dedicatedThread.Join(); // 等待线程终止
Console.ReadLine();
} // 这个方法的前面必须和ParametizedThreadStart委托匹配
private static void ComputeBoundOp(Object state) {
// 这个方法由一个专用线程执行
Console.WriteLine("In ComputeBoundOp: state={0}", state);
Thread.Sleep(1000); // 模拟其它任务(1 秒钟) // 这个方法返回后,专用线程将终止
}
}
- 可以使用线程将代码同其他代码隔离 这将提高应用程序的可靠性。事实上,这正是Windows在操作系统中引入线程概念的原因。
- 可以使线程来简化编码 有的时候,如果通过一个任务自己的线程来执行该任务,编码会变得更简单。通常,在你引入线程时,引入的是要相互协作的代码,它们可能要求线程同步构造知道另一个线程在什么时候终止。一旦开始涉及协作,就要使用更多的资源,同时会使代码变得更复杂。所以,在开发使用线程之前,务必确定线程真的能帮到你。
- 可以用线程来实现并发处理 如果知道自己的应用程序要在多CPU机器上运行,那么让多个任务同时运行,就能提高性能。
线程相对 优先级 |
进程优先级类 |
|||||
---|---|---|---|---|---|---|
Idle |
Below Normal |
Normal |
Above Normal |
High |
Real-Time |
|
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 |
6 |
8 |
11 |
22 |
Idle |
1 |
1 |
1 |
1 |
1 |
16 |
public class Program
{
public static void Main()
{
// 创建一个线程 (默认是前台进程)
Thread t = new Thread(Worker); // 将前台进程变成后台进程
t.IsBackground = true; t.Start(); // 启动线程
// 如果t是一个前台进程,则应用程序大约10秒后才终止
// 如果t是一个后台进程,则应用程序立即终止
Console.WriteLine("Ruturning from Main"); Console.Read();
} private static void Worker()
{
Thread.Sleep(10000); // 模拟做10秒钟工作
Console.WriteLine("Ruturning from Worker");
}
}
[CLR via C#]25. 线程基础的更多相关文章
- 【C#进阶系列】25 线程基础
线程的概念 线程的职责是对CPU进行虚拟化. CPU为每个进程都提供了该进程专用的线程(功能相当于cpu),应用程序如果进入死循环,那么所处的进程会"冻结",但其他进程不会冻结,它 ...
- 25线程基础-CLR
由CLR via C#(第三版) ,摘抄记录... 1.线程是CPU的虚拟化,windows为每个进程提供专用线程(CPU)2.线程开销:内存和时间. 线程内核对象—OS为系统中创建的每个线程都分配并 ...
- 《CLR via C#》读书笔记 之 线程基础
第二十五章 线程基础 2014-06-28 25.1 Windows为什么要支持线程 25.2 线程开销 25.3 停止疯狂 25.6 CLR线程和Windows线程 25.7 使用专用线程执行异步的 ...
- Clr Via C#读书笔记---线程基础
趣闻:我是一个线程:http://kb.cnblogs.com/page/542462/ 进程与线程 进程:应用程序的一个实例使用的资源的集合.每个进程都被赋予了一个虚拟地址空间. 线程:对CPU进行 ...
- 线程基础(CLR via C#)
1.线程基础 1.1.线程职责 线程的职责是对CPU进行虚拟化.Windows 为每个进程豆提供了该进程专用的线程(功能相当于一个CPU).应用程序的代码进入死循环,于那个代码关联的进程会&quo ...
- CLR via C# 读书笔记-26.线程基础
前言 这俩个月没怎么写文章做记录分享,一直在忙项目上线的事情,但是学习这件事情,停下来就感觉难受,clr线程这章也是反复看了好多遍,书读百遍其义自见,今天我们来聊下线程基础 1.进程是什么,以及线程起 ...
- C#多线程编程系列(二)- 线程基础
目录 C#多线程编程系列(二)- 线程基础 1.1 简介 1.2 创建线程 1.3 暂停线程 1.4 线程等待 1.5 终止线程 1.6 检测线程状态 1.7 线程优先级 1.8 前台线程和后台线程 ...
- [CLR via C#]4. 类型基础及类型、对象、栈和堆运行时的相互联系
原文:[CLR via C#]4. 类型基础及类型.对象.栈和堆运行时的相互联系 CLR要求所有类型最终都要从System.Object派生.也就是所,下面的两个定义是完全相同的, //隐式派生自Sy ...
- Qt之线程基础
何为线程 线程与并行处理任务息息相关,就像进程一样.那么,线程与进程有什么区别呢?当你在电子表格上进行数据计算的时候,在相同的桌面上可能有一个播放器正在播放你最喜欢的歌曲.这是一个两个进程并行工作的例 ...
随机推荐
- 手动安装 atom 扩展包 packages
由于某些原因, 我们下载 atom 扩展时发现速度特别慢, 或者根本无法下载, 那我们可以尝试手动安装 首先, 从 github 上下载(或其它地方) 扩展包, 解压 进入该文件夹, 找到 packa ...
- 云计算的三层SPI模型
(转自:http://hi.baidu.com/fengjun8216/item/b15bbef4dcf74049922af27b) 一般而言,云计算架构可以用三层SPI模型来表述. 一.基础设施即服 ...
- IOS RSA 加密方式
采用RSA加密方式,主要是生成公钥和私钥,公钥用来加密,私钥用来解密,至于其中如何实现的,网上有很多原理. 参见如下: https://github.com/jslim89/RSA-objc PS: ...
- 从远程服务器数据库中同步数据到本地数据库 sql server 2008 开启分布
控制面板\所有控制面板项\管理工具 打开“管理工具――组件服务”,以此打开“组件服务――计算机”,在“我的电脑”上点击右键.在MSDTC选项卡中,点击“安全配置”按钮. 在安全配置窗口中做如下设置: ...
- [转]大型 JavaScript 应用架构中的模式
目录 1.我是谁,以及我为什么写这个主题 2.可以用140个字概述这篇文章吗? 3.究竟什么是“大型”JavaScript应用程序? 4.让我们回顾一下当前的架构 5.想得长远一些 6.头脑风暴 7. ...
- TN035: Using Multiple Resource Files and Header Files with Visual C++
TN035: Using Multiple Resource Files and Header Files with Visual C++ This note describes how the Vi ...
- Day One studying english
I start study english lately,but the is no basis for english.Only i use baidu translation,google tra ...
- Backbone之旅——Collection and View篇
上篇文章说了Model,这次说说Collection,collection就是model的集合,用来装载model对象的 定义方法 var Persons = new Backbone.Collect ...
- 『WPF』实现拖动文件到窗体(控件)
前言 实现从窗口外部拖文件到窗口内部并自动捕获文件地址. 第一步 开启属性 启用底层Window的AllowDrop属性,添加Drop事件. Drop事件:当你拖动文件到对应控件后,松开触发. 除Dr ...
- Razor 在WebApp 框架的运用
前面有两章介绍了WebApp框架<WebApp MVC,“不一样”的轻量级互联网应用程序开发框架>和<WebApp MVC 框架的开发细节归纳>,其中视图引擎是用的Nveloc ...