[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之线程基础
何为线程 线程与并行处理任务息息相关,就像进程一样.那么,线程与进程有什么区别呢?当你在电子表格上进行数据计算的时候,在相同的桌面上可能有一个播放器正在播放你最喜欢的歌曲.这是一个两个进程并行工作的例 ...
随机推荐
- 博为iHospital-HIS医院信息系统产品系列
博为软件iHospital-HIS产品系列式面向大中型医院应用的完整医院流程信息化产品,覆盖了医院主要的业务流程,管理职能,和病人在医院诊疗的各个环节.将医院流程的优化与软件系统完美结合,为建立数字化 ...
- 如何升级TeX Live 2014宏包
转:人大经济论坛 LATEX论坛 版,详细出处参考: http://bbs.pinggu.org/forum.php?mod=viewthread&tid=3370640&page=1 ...
- 高吞吐量的分布式发布订阅消息系统Kafka--安装及测试
一.Kafka概述 Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作流数据. 这种动作(网页浏览,搜索和其他用户的行动)是在现代网络上的许多社会功能的一个关键因 ...
- 一次流量稍高导致web项目慢的问题&解决
项目上线后,用户越来越多,有一天出现一个issue:用户访问特别慢. 首先介绍下架构: haproxy/Nginx / \ node1 node2 | | redis redis(slave) | | ...
- android学习者优秀网址推荐
非常漂亮的android UI库集合,别人整理的,如果感觉不错,赶快收藏吧!! https://github.com/wasabeef/awesome-android-ui https://githu ...
- TabHost的用法(转)
本文结合源代码和实例来说明TabHost的用法. 使用TabHost 可以在一个屏幕间进行不同版面的切换,例如android自带的拨号应用,截图: 查看tabhost的源代码,主要实例变量有: pr ...
- 使用linux mint 安装无线网卡驱动
新买了个笔记本Thinkpad E440,用了两天发现无线网非常不稳定,有时候能搜到wifi却连不上,有时候连上了却连不上互联网,于是决定重新安装个网卡驱动. 首先看看自己显卡的型号: lspci : ...
- WebDriver基本API使用(基于Java)V1.0
WebDriver基本API使用(基于Java)V1.0http://www.docin.com/p-803032877.html
- git 在提交之前撤销add操作
问题 在使用git时,在未添加.ignore文件前使用 git add . 将所有文件添加到库中,不小心将一些不需要加入版本库的文件加到了版本库中.由于此时还没有提交所以不存在HEAD版本,不能使用 ...
- 【学】常用hash算法的介绍
基本知识 Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值.这种转换是一种压缩映 ...