C#的多线程简介

C#的多线程简介

     在.NET多线程编程这个系列咱们讲一块儿来探讨多线程编程的各个方面。首先我将在本篇文章的开始向你们介绍多线程的有关概念以及多线程编程的基础知识;在接下来的文章中,我将逐一讲述。NET平台上多线程编程的知识,诸如System.Threading命名空间的重要类以及方法,并就一些例子程序来做说明。
 
引言
 
早期的计算硬件十分复杂,可是操做系统执行的功能确十分的简单。那个时候的操做系统在任一时间点只能执行一个任务,也就是同一时间只能执行一个程序。多个任务的执行必须得轮流执行,在系统里面进行排队等候。因为计算机的发展,要求系统功能愈来愈强大,这个时候出现了分时操做的概念:每一个运行的程序占有必定的处理机时间,当这个占有时间结束后,在等待队列等待处理器资源的下一个程序就开始投入运行。注意这里的程序在占有必定的处理器时间后并无运行完毕,可能须要再一次或屡次分配处理器时间。那么从这里能够看出,这样的执行方式显然是多个程序的并行执行,可是在宏观上,咱们感受到多个任务是同时执行的,所以多任务的概念就诞生了。每一个运行的程序都有本身的内存空间,本身的堆栈和环境变量设置。每个程序对应一个进程,表明着执行一个大的任务。一个进程能够启动另一个进程,这个被启动的进程称为子进程。父进程和子进程的执行只有逻辑上的前后关系,并无其余的关系,也就是说他们的执行是独立的。可是,可能一个大的程序(表明着一个大的任务),能够分割成不少的小任务,为了功能上的须要也有多是为了加快运行的速度,可能须要同一时间执行多个任务(每一个任务分配一个多线程来执行相应的任务)。举个例子来讲,你正在经过你的web浏览器查看一些精彩的文章,你须要把好的文章给下载下来,可能有些很是精彩的文章你须要收藏起来,你就用你的打印机打印这些在线的文章。在这里,浏览器一边下载HTML格式的文章,一边还要打印文章。这就是一个程序同时执行多个任务,每一个任务分配一个线程来完成。所以咱们能够看出一个程序同时执行多个任务的能力是经过多线程来实现的。
 
多线程VS多任务
 
正如上面所说的,多任务是相对与操做系统而言,指的是同一时间执行多个程序的能力,虽然这么说,可是实际上在只有一个CPU的条件下不可能同时执行两个以上的程序。CPU在程序之间作高速的切换,使得全部的程序在很短的时间以内能够获得更小的CPU时间,这样从用户的角度来看就好象是同时在执行多个程序。多线程相对于操做系统而言,指的是能够同时执行同一个程序的不一样部分的能力,每一个执行的部分被成为线程。因此在编写应用程序时,咱们必须得很好的设计以免不一样的线程执行时的相互干扰。这样有助于咱们设计健壮的程序,使得咱们能够在随时须要的时候添加线程。
 
线程的概念
 
线程能够被描述为一个微进程,它拥有起点,执行的顺序系列和一个终点。它负责维护本身的堆栈,这些堆栈用于异常处理,优先级调度和其余一些系统从新恢复线程执行时须要的信息。从这个概念看来,好像线程与进程没有任何的区别,实际上线程与进程是确定有区别的:
一个完整的进程拥有本身独立的内存空间和数据,可是同一个进程内的线程是共享内存空间和数据的。一个进程对应着一段程序,它是由一些在同一个程序里面独立的同时的运行的线程组成的。线程有时也被称为并行运行在程序里的轻量级进程,线程被称为是轻量级进程是由于它的运行依赖与进程提供的上下文环境,而且使用的是进程的资源。
在一个进程里,线程的调度有抢占式或者非抢占的模式。
在抢占模式下,操做系统负责分配CPU时间给各个进程,一旦当前的进程使用完分配给本身的CPU时间,操做系统将决定下一个占用CPU时间的是哪个线程。所以操做系统将按期的中断当前正在执行的线程,将CPU分配给在等待队列的下一个线程。因此任何一个线程都不能独占CPU。每一个线程占用CPU的时间取决于进程和操做系统。进程分配给每一个线程的时间很短,以致于咱们感受全部的线程是同时执行的。实际上,系统运行每一个进程的时间有2毫秒,而后调度其余的线程。它同时他维持着全部的线程和循环,分配不多量的CPU时间给线程。 线程的的切换和调度是如此之快,以致于感受是全部的线程是同步执行的。
 
调度是什么意思?调度意味着处理器存储着将要执行完CPU时间的进程的状态和未来某个时间装载这个进程的状态而恢复其运行。然而这种方式也有不足之处,一个线程能够在任何给定的时间中断另一个线程的执行。假设一个线程正在向一个文件作写操做,而另一个线程中断其运行,也向同一个文件作写操做。 Windows 95/NT, UNIX使用的就是这种线程调度方式。
在非抢占的调度模式下,每一个线程能够须要CPU多少时间就占用CPU多少时间。在这种调度方式下,可能一个执行时间很长的线程使得其余全部须要CPU的线程”饿死”。在处理机空闲,即该进程没有使用CPU时,系统能够容许其余的进程暂时使用CPU。占用CPU的线程拥有对CPU的控制权,只有它本身主动释放CPU时,其余的线程才可使用CPU。一些I/O和Windows 3。x就是使用这种调度策略。
在有些操做系统里面,这两种调度策略都会用到。非抢占的调度策略在线程运行优先级通常时用到,而对于高优先级的线程调度则多采用抢占式的调度策略。若是你不肯定系统采用的是那种调度策略,假设抢占的调度策略不可用是比较安全的。在设计应用程序的时候,咱们认为那些占用CPU时间比较多的线程在必定的间隔是会释放CPU的控制权的,这时候系统会查看那些在等待队列里面的与当前运行的线程同一优先级或者更高的优先级的线程,而让这些线程得以使用CPU。若是系统找到一个这样的线程,就当即暂停当前执行的线程和激活知足条件的线程。若是没有找到同一优先级或更高级的线程,当前线程还继续占有CPU。当正在执行的线程想释放CPU的控制权给一个低优先级的线程,当前线程就转入睡眠状态而让低优先级的线程占有CPU。
在多处理器系统,操做系统会将这些独立的线程分配给不一样的处理器执行,这样将会大大的加快程序的运行。线程执行的效率也会获得很大的提升,由于将线程的分时共享单处理器变成了分布式的多处理器执行。这种多处理器在三维建模和图形处理是很是有用的。
 
须要多线程吗
 
咱们发出了一个打印的命令,要求打印机进行打印任务,假设这时候计算机中止了响应而打印机还在工做,那岂不是咱们的中止手上的事情就等着这慢速的打印机打印?所幸的是,这种状况不会发生,咱们在打印机工做的时候还能够同时听音乐或者画图。由于咱们使用了独立的多线程来执行这些任务。你可能会对多个用户同时访问数据库或者web服务器感到吃惊,他们是怎么工做的?这是由于为每一个链接到数据库或者web服务器的用户创建了独立的线程来维护用户的状态。若是一个程序的运行有必定的顺序,这时候采用这种方式可能会出现问题,甚至致使整个程序崩溃。若是程序能够分红独立的不一样的任务,使用多线程,即便某一部分任务失败了,对其余的也没有影响,不会致使整个程序崩溃。
 
毫无疑问的是,编写多线程程序使得你有了一个利器能够驾奴非多线程的程序,可是多线程也可能成为一个负担或者须要不小的代价。若是使用的不当,会带来更多的坏处。若是一个程序有不少的线程,那么其余程序的线程必然只能占用更少的CPU时间;并且大量的CPU时间是用于线程调度的;操做系统也须要足够的内存空间来维护每一个线程的上下文信息;所以,大量的线程会下降系统的运行效率。所以,若是使用多线程的话,程序的多线程必须设计的很好,不然带来的好处将远小于坏处。所以使用多线程咱们必须当心的处理这些线程的建立,调度和释放工做。
 
多线程程序设计提示
 
有多种方法能够设计多线程的应用程序。正如后面的文章所示,我将给出详细的编程示例,经过这些例子,你将能够更好的理解多线程。线程能够有不一样的优先级,举例子来讲,在咱们的应用程序里面,绘制图形或者作大量运算的同时要接受用户的输入,显然用户的输入须要获得第一时间的响应,而图形绘制或者运算则须要大量的时间,暂停一下问题不大,所以用户输入线程将须要高的清闲级,而图形绘制或者运算低优先级便可。这些线程之间相互独立,相互不影响。
在上面的例子中,图形绘制或者大量的运算显然是须要站用不少的CPU时间的,在这段时间,用户没有必要等着他们执行完毕再输入信息,所以咱们将程序设计成独立的两个线程,一个负责用户的输入,一个负责处理那些耗时很长的任务。这将使得程序更加灵活,可以快速响应。同时也可使得用户在运行的任什么时候候取消任务的可能。在这个绘制图形的例子中,程序应该始终负责接收系统发来的消息。若是因为程序忙于一个任务,有可能会致使屏幕变成空白,这显然须要咱们的程序来处理这样的事件。因此我必须得有一个线程负责来处理这些消息,正如刚才所说的应该触发重画屏幕的工做。
咱们应该把握一个原则,对于那些对时间要求比较紧迫须要当即获得相应的任务,咱们因该给予高的优先级,而其余的线程优先级应该低于她的优先级。侦听客户端请求的线程应该始终是高的优先级,对于一个与用户交互的用户界面的任务来讲,它须要获得第一时间的响应,其优先级因该高优先级。
 
相关文章
相关标签/搜索