.NET 多线程必须搞清楚的几个问题

来源:互联网 发布:龙桃子淘宝下架 编辑:程序博客网 时间:2024/06/12 01:20

Windows进程和线程的概念

进程

进程不过是应用程序的一个实例要使用的资源的集合。一个进程使用的代码和数据无法由另一个进程访问

线程

作为一个Windows概念,线程(Thread)的职责是对CPU进行虚拟化。Windows为每个进程都提供了该进程专用的线程(功能相当于一个CPU,可将线程理解成一个逻辑CPU)。

 

CLR线程的概念

目前、一个CLR线程对应一个Windows线程。相信将来CLR团队会将CLR线程和Windows线程分离,引入CLR自己的逻辑线程概念,使一个CLR逻辑线程不一定映射到一个Windows线程。据说,CLR逻辑线程将使用比windows线程少的多的资源,所以能在极少的windows线程上运行大量的CLR逻辑线程。

 

 

 

1.线程是如何被创建的,要分配哪些资源?

 线程的开销,以X86计算机为例。

(1)线程内核对象(thread kernel object),该对象包含了一组对线程进行描述的属性和线程上下文。上下文是一个内存块,其中包含了CPU的寄存器集合。线程上下文使用约700字节(约0.7KB)的内存。

(2)线程环境块(thread environment block,TEB) TEB是在用户模式(应用程序代码块能快速访问的空间)中分配和初始化一个内存块。TEB耗费一个内存页(4KB).

(3)用户模式栈(user-mode stack) 用户模式栈用于存储传给方法的局部变量和实参。它还包含一个地址:指出当前方法返回时,线程接着应该从什么地方开始执行。默认情况下windows为每个用户模式栈分配1MB内存。

(4)内核模式栈(kernel-mode stack) 应用程序代码向操作系统中的一个内核模式的函数传递实参时,还会使用内核模式栈。出于安全方面的原因,针对从用户模式的代码传给内核的任何实参,Windows都会把它们从线程的用户模式栈复制到线程的内核模式栈。一经复制,内核就可验证实参的值。由于应用程序代码不能访问内核模式栈,所以应用程序无法修改验证之后的实参值。内核模式栈大小为12KB。

(5)DLL线程连接(attach)和线程分离(detach)通知 Windows的一个策略是,任何时候在进程中创建一个线程,都会调用那个进程中加载的所有DLL的DllMain方法,并想该方法传递一个DLL_THREAD_ATTACH标志。类似地,任何时候一个线程终止,都会调用进程中的所有DLL的DllMain方法,并向该方法传递一个DLL_THREAD_DETACH标志。有的DLL需要利用这些通知,为进程中创建/销毁的每个线程执行一些特殊的初始化或(资源)清理操作。

 

2.线程是如何销毁的,要释放哪些资源?

 在Windows的早期岁月,许多进程只加载5个或者6个DLL。但是如今,有的进程可能加载几个百个DLL。例如Microsoft Office Outlook在它的进程地址空间中加载了大约250个DLL!这意味着每次在Office Outlook中创建一个新线程,都必须先调用250个DLL函数,然后线程才能开始做他设计做的事情。Outlook中的线程终止时,这250个函数还要再调用一遍。这严重影响了在进程中创建和消费线程时的性能。

 

3.上下文切换

Windows必须在系统中所有线程(逻辑CPU)之间共享物理CPU。

在任何时刻,Windows只将一个线程分配给一个CPU。那个线程允许运行一个时间片。一旦时间片到期,Windows就上下文切换到另一个线程。每次上下问切换,Windows都要执行以下操作。

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

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

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

上下文切换完成后,CPU执行所选的线程,直到它的时间片到期。然后,会发生另一次上下文切换。Windows大约每30毫秒执行一次上下文切换。上下文切换是净开销;也就是说,上下文切换所产生的开销不会换来任何内存或性能上的收益。Windows执行上下文切换,向用户提供一个健壮的、响应灵敏的操作系统。

 

 

4.各个状态下的线程,在干什么?状态切换时的系统开销。

 

 

5.多线程共享资源(代码、全局变量)的机制。

 

 

6.线程池是如何工作的?

 

 

7.线程池的是全局共享的吗?

 

 

8.高使用线程池会有哪些影响?

 

 

9.在什么情况下应该使用线程池?在什么情况下不应该使用线程池?

 

 

原创粉丝点击