
在"开始"->"运行"中输入"drwtsn32"命令,或者"开始"->"程序"->"附件"->" 系统工具"->"系统信息"->"工具"->"dr watson",调出系统里的华医生dr.watson ,只保留"转储全部线程上下文"选项,否则一旦程序出错,硬盘会读很久,并占用大量空间。内核线程(kernel thread, klt)就是直接由操作系统内核支持的线程,这种线程由内核来完成线程切换,内核通过操作调度器对线程进行调度,并负责将线程的任务映射到各个处理器上。不过这个操作有危险就不做了,原因是windows平台下,java的线程是直接映射到操作系统的内核线程上的,如果写个死循环无限产生线程,那么可能会造成操作系统的假死。
在新的OS内核中,进程实际是应用程序的实例要使用的资源的集合。每个进行都被赋予了一个虚拟地址空间,确保在一个进程中使用的代码和数据不会被另外一个进行所访问。而线程的职责是对CPU进行逻辑的虚拟化。
线程的开销
在创建,销毁一个线程的过程中,存在着一些巨大的开销。这些开销有时间上,也有空间上面的。
线程内核对象(Thread-kernel object)
这种数据结构包含着一组对线程进行描述的属性,这些属性一般是用于CPU的调度多线程编程,例如线程的优先级,等待的时间等等。同时还包括了线程的上下文(Thread Contexgt),这是CPU寄存器集合的内存块所存放的信息的副本。

线程环境块(thread environment block)
TEB是在用户模式中分配的初始化的内存块。TEB耗用一个内存页(4KB)。TEB包含着异常处理链首。线程进入的每个try块都在链首插入一个节点;线程推出try块是,从链表中删除该节点。TEB还包含着线程的“线程本地存储”数据,以及由GDI和OpenGL图形使用的一些数据结构。
用户模式栈(User-model stack)
这就是常说的用户栈,用于存放传给方法的形参和方法中自定义的实参,已经当前方法返回的时候,线程应该从那个地方开始执行。Windows的默认用户模式栈的大小为1M。
内核模式栈
当应用程序代码想操作系统中的内核模式函数传递实参时,还会使用内核模式栈。出于对安全的考虑,所有由应用程序向内核函数传递的参数,都会先复制到内核模式栈中。由于程序不能访问内核模式栈,所以参数一经复制过去内核模式栈中,程序便不能修改其值。其实这个内核模式栈在功能上跟用户模式栈的作用是一样的,都是用于存储传给方法的形参,已经方法中自定义的实参,以及函数的返回地址。特别之处就是,应用程序不能修改里面的值,只能由内核函数进行修改,从而达到了安全。

DLL线程连接和线程分离通知
上面所说的三个开销都是对于内存的开销,这个DLL线程连接和线程分离通知却是时间上面的开销。不过这也是相对的来说的,因为上面的三个开销,在分配内存,初始化内存过程中,也必须花费很多的时间。在创建一个新的线程的时候,Windows都会调用进程中加载的所有非托管DLL的DllMain方法,并向这个方法传递一个DLL_THREAD_ATTCH标志。类似的,终止线程的时候,也会调用这个DllMain方法,并传递一个DLL_THREAD_DETACH标志。因为有些DLL需要获取这些通知,才能为进程中创建/销毁的每个线程执行特殊的初始化或者清理操作。事实上,每个进程都会加载很多非托管的DLL文件,所以初始化或者销毁一个线程,便需要调用多个的DllMain方法。
CPU调度时上下文切换的开销
上下文切换的开销主要集中在两个方面:
不使用ThreadPool而自己创建一个线程的原则
一般情况下,要为不会阻止其他线程的相对较短的任务处理多个线程并且不需要对这些任务执行任何特定调度时,使用 ThreadPool 类是一种最简单的方式。 但是,有多个理由创建您自己的线程:

线程的优先级
已实现的调度程序有:基于优先级的抢占式调度和edf调度。可抢占线程就是说,在该线程用完自己的时间片以后,操作系统会强制把该线程切出,以便执行其他线程。ecos支持优先级的抢占式调度和轮转调度相结合的mlq(multi level queue)调度器,基于优先级的抢占式调度的bitmap位图调度器,lottery抽签调度器,三种调度器只是在cyg_scheduler_implementation类的定义上有所区别。
在实际编程中,我们是看不到这0-31的优先级的,这是因为Windows只是公开了这些优先级的一个抽象。特别要说明的的是,线程的优先级由进程的优先级类和线程的相对优先级来决定。
进程优先级类
相对线程优先级
Below Normal

Above Normal
Time-Cirtical
Above Normal
Below Normal
这里要特别说明的是,Windows为自己保留了优先级0和Realtime范围,同时CLR也为自己保留了Idle和Time-Cirtical范围的优先级。程序的线程绝对优先级是由进程优先级类和相对线程优先级所共同决定的,同时我们不应该去更改进程的优先级。因为在正常情况下,进程根据其启动它的进程来分配优先级。大多数进程都是由Windows资源管理器启动,后者在Normal优先级类中生成他们的所有子进程。所以我们在Thread.Priority中只有Highest,Above Normal,Noraml,Below Normal,Lowset这几种,相对应的优先级是6,7,8,9,10。



图1 Spy++中查看Chrome的某个线程的信息
前台线程和后台线程
apache是多进程/多线程模型的,它会在启动的时候启动一批进程,作为进程池,当用户请求到来的时候,从进程池中分配处理进程给具体的用户请求,这样可以节省多进程/线程的创建和销毁开销,但是如果同时有大量的请求过来,还是需要消耗比较高的进程/线程切换。d、setdeamon:把该线程组设置为后台线程组,后台线程具有一个特征,当后台线程的最后一个线程执行结束或最后一个线程被销毁,后台线程组自动销毁。后台线程也称作精灵线程,是一种为前台进程提供服务的进程多线程编程,后台线程并不是不可或缺的线程,即实质可有可无。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-106825-1.html
越南就是这种人