线程与线程池

1.       线程基础

Windows中,线程的职责是对CPU进行虚拟化,可将线程理解为一个逻辑CPU。Windows为每个进程提供该进程专用的线程。

由于线程是对CPU进行虚拟化,使得线程会产生空间(内存耗用)和时间(上下文切换)上的开销。

  1.        空间开销:在默认情况下,Windows为每个线程的用户模式栈分配1MB内存。

  2.        时间开销:在任何给定的时刻,Windows只将一个线程分配给一个CPU。该线程允许运行一个“时间片”。一旦时间片到期,Windows就上下文切换到另一个线程。Windows执行一次上下文切换大约需要30毫秒。

结论:尽可能避免使用线程,但有时必须使用线程来提高程序的响应速度和执行多任务。

2.       前后台线程

在CLR中的线程只有前台线程和后台线程两种。一个进程中所有前台线程都停止运行时,CLR将强制终止所有正在运行的后台线程,并且不会抛出异常。只要有一个前台线程在运行,应用程序的进程就在运行。所以前台线程适合执行关键任务,后台现在适合执行非关键任务。下面代码用于说明前后台线程与进程的关系。

 private static void Main(string[] args)
        {
            //创建专用线程
            var t = new Thread(ThreadWork)
                {
                    Name = "NewThread1",
                    //指定是否为后台线程,修改该属性验证前后台线程与进程的关系
                    IsBackground = false
                };
            //创建专用线程
            
            t.Start();
            Console.WriteLine("进程结束");
            
        }

        private static void ThreadWork()
        {
            Console.WriteLine("线程启动:" + Thread.CurrentThread.Name);
            //让当前线程休眠3秒钟,把线程执行权让给优先级高的其他线程执行,
            //避免一直占有线程执行权。3秒钟过后线程醒来,一定能立即恢复执行。
            //这是因为在那个时刻,其它线程可能正在运行而且没有被调度为放弃执行,除非
            //1、“醒来”的线程具有更高的优先级
            //2、正在运行的线程因为其它原因而阻塞。
            Thread.Sleep(3000);
            Console.WriteLine("线程完成" + Thread.CurrentThread.Name);
             
            //这个方法返回后,该专用线程将终止。
           
        }

 

3.       线程池

3.1.    线程池基础

由第一节线程基础的结论可知,我们应该在保持代码响应能力的同时创建尽可能少的线程。CLR线程使用Windows的线程处理能力,一个CLR线程直接对应一个Windows线程。为了改善创建和销毁线程带来的空间和时间上的开销,CLR包含代码来管理它自己的线程池。可将线程池想象为可由你的应用程序使用的一个线程集合。每个CLR一个线程池。

CLR初始化时,线程池中没有线程。在内部,线程池维护一个操作请求队列。应用程序向线程池发出一个请求时,如果线程池中没有线程,就创建一个新线程用于处理应用程序的请求。当线程池中的线程完成任务后,线程不会被销毁,而是返回到线程池中,并且进入空闲状态,等待响应另一个请求。由于线程池中的线程处理完任务后不销毁自身,所以不再产生额外的性能损失。如果应用程序停止向线程池发出请求,线程池中的线程都处于空闲状态,一段时间后,线程会自己醒来终止自己并且释放资源。线程终止自己时会产生一定的性能损失,然而,线程池中的线程终止自己是因为闲得慌,说明应用程序本身没做什么事,所以这个性能损失关系不大。

3.2.    线程池管理

不同CLR的版本,其内部结构有一定的变化。最好将线程池看成黑盒子。目前,线程池的工作非常理想,强烈建议信任它。

  1.        设置线程池上限

CLR允许开发人员设置线程池的最大线程数,但永远都不应该为线程池设置上限,因为可能发生饥饿或死锁。由于存在饥饿和死锁问题,所以CLR团队一直都在稳步增加线程池默认能够拥有的最大线程数,目前默认值为1000个线程。

 

注:参考CLR via C#第三版 第25、26章

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章