您的位置:首页 > 编程语言 > C#

C# 线程手册 第五章 扩展多线程应用程序 CLR 和 线程

2012-04-03 22:35 363 查看
设计CLR 的目的是创建一个提供多种服务(比如编译、垃圾回收、内存管理以及基于.NET 平台的线程池技术)的托管代码环境。

当然,Win32 平台和.NET Framework 平台在定义我们的应用程序使用的用来作为线程宿主的进程方面是不同的。在传统Win32 应用程序中,每个进程都由一个线程集合组成。如果一台机器仅有一个CPU,那么每个线程都要与其他线程交换线程本地存储和调用堆栈以实现时间轮转。单一处理器基于线程优先级来为每个线程分配时间片。当一个特定线程的时间片用完以后,它会被暂停执行同时其他线程被允许执行它的任务。在.NET Framework 中,每个Win32 进程都被逻辑上划分为同时寄宿线程、TLS以及调用堆栈的应用程序域。值得一提的是应用程序域间的通信由.NET Framework 中一个称为Remoting 的技术处理。

到目前为止,我们已经有了关于线程池和.NET 进程的基本概念,让我们进一步看看CLR 是如何为.NET 应用程序提供线程池功能的。

CLR 在线程池中的作用

CLR 组成了.NET Framework 的核心部分,它提供多个服务用于管理应用程序,线程池就是其中之一。对在线程池中执行的任务(工作组件)来说,CLR 从线程池中取出一个线程来执行特定任务(一个工作线程)并在任务完成后把线程还给线程池。

CLR 使用一个多线程单元模型、高性能队列以及抢占式多任务分发来实现线程池。这是一个将CPU 时间分成多个时间片的过程。在每个时间片中,只有一个线程在执行而其他线程必须等待。一旦时间片用完,其他线程被允许按照自身线程优先级的高低来使用CPU。客户端请求被放在任务队列中,队列中的每个任务被分发给线程池中第一个可用的线程。

一旦线程完成了分配给它的任务,它就会返回给线程池并等待CLR 给它分配下一个任务。线程池的大小可以是确定的也可以是动态的。如果是前者,线程池中线程的数量在线程池的整个生命周期内不会有变化。通常情况下,当我们确定我们的应用程序将要使用的资源时候可以使用这种类型的线程池,在线程池初始化时就确定线程的数目。当我们为一个局域网开发解决方案或者我们完全按照目的平台的系统要求来定义应用程序时可以使用这种方案。当我们不知道可用资源大小的时候就使用动态线程池大小,一个web 服务器不会知道有多少个客户端请求需要其并发处理。

使用线程池的注意事项

毫无疑问线程池给我们提供了很多好处以便于我们创建多线程应用程序,但是有一些情况我们不应该使用线程池。下面的列表指出哪些情况下我们不应该使用线程池:

1. CLR 从线程池获取一个线程并把它指定给一个任务,当任务完成后CLR 回收线程。一旦任务被加入到队列中以后,没有直接的方式可以取消任务。

2. 对于生命周期比较短的任务来说线程池是一种高效解决方案,比如一个web 服务器负责处理客户端对指定文件的请求。线程池不应该用于长时间运行的任务。

3. 线程池是一种按照成本效益形式部署线程的技术,成本效益由运行数量和启动开销决定。应当谨慎行事,以确定线程池的利用率。线程池的大小应该是由其使用率确定。

4. 线程池中的所有线程都是多线程单元。如果你想让线程运行在单线程单元的话,那么线程池无法实现。

5. 如果需要确定线程并执行多种操作,比如启动,阻塞和异常终止的话,那么线程池无法实现。

6. 线程池中用于来运行任务的线程优先级无法设置。

7. 任务指定的应用程序域只有一个线程池。

8. 如果线程池中指定给一个任务的线程锁住了,那么被锁住的线程用来不会被释放回线程池以备再次使用。这种情况可以通过高效编程能力避免。

线程池的大小

.NET Framework 中的ThreadPool类在System.Threading 命名空间里。一个线程池中可以放置的任务数目由计算机中可用内存数量决定。同时,一个进程中可以激活的线程数量由计算机中CPU 数量决定。这是因为每个处理器在每个时刻只能运行一个线程。默认情况下,线程池中的每个线程执行默认任务并按照默认优先级在多线程单元中运行。看起来默认使用的是default 关键字。这并不意外。每个系统都有不同的默认优先级。如果一个线程空闲那么线程池将会调入工作线程以便让所有处理器都忙起来。如果线程池中的所有线程都很忙且当前队列中的任务没有资源执行那么它会生成新线程来执行对应任务。然而,创建的线程数量不能超过最大线程数。默认情况下,每个处理器可以创建25个线程池线程。然而,这个数量可以通过mascoree.h 中的CorSetMaxThreads 成员进行修改。如果有额外的线程请求,请求会被放入队列中知道一些线程完成自己的任务并返回到线程池中。.NET Framework 使用线程池处理异步调用, 创建套接字连接和注册等待操作。

下一篇介绍ThreadPool 类…
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: