25线程基础-CLR

由CLR via C#(第三版) ,摘抄记录...

1、线程是CPU的虚拟化,windows为每个进程提供专用线程(CPU)
2、线程开销:内存和时间。
线程内核对象—OS为系统中创建的每个线程都分配并初始化这种数据结构之一。其中包含对线程进行描述的属性,和上下文。上下文是内存块,x86的是约700字节,x64是约1240,ia64是2500。
线程环境块TEB,用户模式中的内存块(应用程序代码能快速访问的空间),一个TEB一个内存页,x86和x64都是4KB,IA64是8KB。 TEB包含线程的异常处理链首(head)。进入每一个try都在后面插入一个节点,退出try时删除该节点。 TEB还包含线程的本地存储 数据,以及GDI和OpenGL图形使用的数据。
用户模式栈 存储传递给方法的局部变量和实参,还包含一个地址,指出方法返回时,线程从何处执行。默认1MB。
内核模式栈 32位windows下为12KB,64的是24KB。
DLL线程连接和线程分离通知 windows策略决定。。C#和其他托管语言的DLL没有DLLMain函数,不收通知,这提升性能。

3、windows只将一个线程分配给一个CPU,允许其运行一个 时间片 ,上下文切换。
切换:将cpu寄存器的值保存内核对象内部的上下文结构中,选出一个新线程供调度,将其内的上下文结构值加载到CPU。
大约每30毫秒执行一次切换。净开销。而且还会切换高速缓存cache。尽可能避免切换。
时间片结束时,如果windows决定再调度同一线程,就没有切换。这显著改进性能

4、垃圾回收时,CLR暂停所有线程,遍历他们的栈进行标记,再遍历栈,再恢复所有线程。所以,减少线程数量会显著提升垃圾回收器的性能。调试时也挂起,线程越多,调试体验越差
单个线程不会在多个内核CPU上调度,应在确保响应能力的同时创建尽量少的线程。理性使用线程。

5、超线程CPU,芯片中包含2组架构状态,只有一组在执行,对于windows,看起来像是2个CPU,所有windows会同时调度2个线程。芯片一次只能执行一个。

6、NUMA架构机器,(略)

7、CLR线程和windows线程: CLR使用的是windows的线程处理能力。一个CLR线程直接对应一个windows线程。

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

  建议避免采用,应尽量使用CLR的线程池来执行异步计算限制操作。

  显示创建自己线程的条件:

    优先级高,不建议更改线程池的优先级;

    表现为一个前台线程,防止应用程序在线程结束它的任务之前终止。线程池中的是后台线程。

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

    要调用Abort方法提前终止它。

  Thread.Join()等待线程终结

9、使用线程的理由     代码隔离健壮性,简化编码,并发。

  观点改变,CPU计算能力富余,应大胆消费。

10、线程调度和优先级  

   抢占式操作系统,使用算法判断在什么时间调度哪些线程多少时间。

  一个时间片后,windows检查现有所有线程内核对象,有资源的适合调度。从spy++可以查看切换的次数。线程在任何时间可以被抢占,windows调度另一个。你不能阻止其他线程的运行。

     所以,windows是抢占式操作系统,不是实时操作系统,CLR使托管代码的行为更不实时。比如:DLL的JIT加载,代码的JIT编译,GC无法预测的介入。

       线程优先级从0(最低)-31(最高),系统启动时有个为0的零页线程的特殊线程,唯一一个0的线程,在没有其他进程要调度时,将系统RAM所有空闲页清零。

  优先级类(priority class) :Idle,Below Normal,Normal,Above Normal,High和Realtime。 优先级类是用于进程的。每个线程的优先级取决于 他所属的进程的优先级类和在该进程内他自身的优先级——俩者合成基础优先级——动态优先级是OS确保线程可响应,不一直饥饿所产生。但是16-31之间的线程,系统不提升他们的优先级。0-15的才提升。

  应用开发人员永远不直接处理优先级。Normal的Normal是8,大多数程序都是8的优先级。Windwos永远不会调度进程,只调度线程。进程根据启动它的进程来分配一个优先级。大多数进程都是windows资源管理器启动的,属于Normal。

  托管应用程序不应该表现为拥有自己的进程;相反,他们应该表现为在一个AppDomain中运行。 可以更改他的线程相对优先级,设置Thread的Priority属性。System.Diagnostics命名空间包含一个Process类和ProcessThread类,提供进程和线程的windows视图。AppDomain和Thread类,公开了应用域和线程的CLR视图。

11、 前台线程和后台线程

   线程在CLR中要么是前台,要么是后台。一个进程中的所有前台停止时,CLR强制终止扔在运行的任何后台线程。--直接终止,不抛出异常。

  

 1     public static void Main()
 2         {
 3             //  创建一个新线程(默认为前台线程)
 4             Thread t = new Thread(Worker);
 5 
 6             Console.WriteLine(t.IsBackground.ToString());
 7             //  使线程成为一个后台线程
 8             t.IsBackground = true;
 9             t.Start(); //  启动线程
10             //  如果 t 是一个前台线程,则应用程序大约 10 秒后才终止
11             //  如果 t 是一个后台线程,则应用程序立即终止
12             Console.WriteLine("Returning from Main");
13             Console.Read();
14 
15         }
16         private static void Worker()
17         {
18             Thread.Sleep(10000); //  模拟做 10 秒钟的工作
19             //  下面这一行代码,只有在由一个前台线程执行时,才会显示出来
20             Console.WriteLine("Returning from Worker");
21 
22             Console.Read();
23         }
24     }
后台线程

  在线程生存期内,随时可前后变换。应用的主线程以及通过Thread对象显示创建的都默认前台,线程池默认后台。由进入托管执行环境的本地代码创建的线程被标记为后台。应尽量避免使用前台线程

   wintellect类库,作者写的....

~~~~~~~~~~待续~~

posted @ 2015-04-01 01:44  北落师门α  阅读(286)  评论(0编辑  收藏  举报