高级多线程编程

上传人:kms****20 文档编号:46615607 上传时间:2018-06-27 格式:PDF 页数:17 大小:70.73KB
返回 下载 相关 举报
高级多线程编程_第1页
第1页 / 共17页
高级多线程编程_第2页
第2页 / 共17页
高级多线程编程_第3页
第3页 / 共17页
高级多线程编程_第4页
第4页 / 共17页
高级多线程编程_第5页
第5页 / 共17页
点击查看更多>>
资源描述

《高级多线程编程》由会员分享,可在线阅读,更多相关《高级多线程编程(17页珍藏版)》请在金锄头文库上搜索。

1、.NET 多线程编程多线程编程 在.NET 多线程编程这个系列我们将一起来探讨多线程编程的各个方面。 在文 的开始向大家介绍多线程的有关概念以及多线程编程的基础知识; 在接下来的文 章中,我将逐一讲述.NET 平台上多线程编程的知识,诸如 System.Threading 命 名空间的重要类以及方法,并就一些例子程序来做说明。 一多任务和多线程一多任务和多线程 引言引言 早期的计算硬件十分复杂,但是操作系统执行的功能确十分的简单。那个时 候的操作系统在任一时间点只能执行一个任务, 也就是同一时间只能执行一个程 序。多个任务的执行必须得轮流执行,在系统里面进行排队等候。由于计算机的 发展,要求系

2、统功能越来越强大,这个时候出现了分时操作的概念:每个运行的 程序占有一定的处理机时间,当这个占有时间结束后,在等待队列等待处理器资 源的下一个程序就开始投入运行。 注意这里的程序在占有一定的处理器时间后并 没有运行完毕,可能需要再一次或多次分配处理器时间。那么从这里可以看出, 这样的执行方式显然是多个程序的并行执行,但是在宏观上,我们感觉到多个任 务是同时执行的,因此多任务的概念就诞生了。每个运行的程序都有自己的内存 空间,自己的堆栈和环境变量设置。每一个程序对应一个进程,代表着执行一个 大的任务。一个进程可以启动另外一个进程,这个被启动的进程称为子进程。父 进程和子进程的执行只有逻辑上的先后

3、关系,并没有其他的关系,也就是说他们 的执行是独立的。但是,可能一个大的程序(代表着一个大的任务) ,可以分割 成很多的小任务,为了功能上的需要也有可能是为了加快运行的速度,可能需要 同一时间执行多个任务(每个任务分配一个多线程来执行相应的任务)。 举个例子 来说,你正在通过你的 web 浏览器查看一些精彩的文章,你需要把好的文章给下 载下来,可能有些非常精彩的文章你需要收藏起来,你就用你的打印机打印这些 在线的文章。在这里,浏览器一边下载 HTML 格式的文章,一边还要打印文章。 这就是一个程序同时执行多个任务,每个任务分配一个线程来完成。因此我们可 以看出一个程序同时执行多个任务的能力是通

4、过多线程来实现的。 多线程多线程 VS 多任务多任务 正如上面所说的,多任务是相对与操作系统而言,指的是同一时间执行多个 程序的能力,虽然这么说,但是实际上在只有一个 CPU 的条件下不可能同时执行 两个以上的程序。CPU 在程序之间做高速的切换,使得所有的程序在很短的时间 之内可以得到更小的 CPU 时间, 这样从用户的角度来看就好像是同时在执行多个 程序。多线程相对于操作系统而言,指的是可以同时执行同一个程序的不同部分 的能力,每个执行的部分被成为线程。所以在编写应用程序时,我们必须得很好的设计以 避免不同的线程执行时的相互干扰。 这样有助于我们设计健壮的程序, 使得我们可以在随时需要的时

5、候添加线程。 线程的概念线程的概念 线程可以被描述为一个微进程,它拥有起点,执行的顺序系列和一个终点。 它负责维护自己的堆栈,这些堆栈用于异常处理,优先级调度和其他一些系统重 新恢复线程执行时需要的信息。从这个概念看来,好像线程与进程没有任何的区 别,实际上线程与进程是肯定有区别的: 一个完整的进程拥有自己独立的内存空间和数据,但是同一个进程内的线程 是共享内存空间和数据的。一个进程对应着一段程序,它是由一些在同一个程序 里面独立的同时的运行的线程组成的。 线程有时也被称为并行运行在程序里的轻 量级进程, 线程被称为是轻量级进程是因为它的运行依赖与进程提供的上下文环 境,并且使用的是进程的资源

6、。 在一个进程里,线程的调度有抢占式和非抢占的模式。 在抢占模式下,操作系统负责分配时间给各个进程,一旦当前的进程 使用完分配给自己的时间, 操作系统将决定下一个占用时间的是哪 一个线程。因此操作系统将定期的中断当前正在执行的线程,将分配给在 等待队列的下一个线程。所以任何一个线程都不能独占。每个线程占用 的时间取决于进程和操作系统。进程分配给每个线程的时间很短,以至于我 们感觉所有的线程是同时执行的。实际上,系统运行每个进程的时间有 2 毫秒, 然后调度其他的线程。它同时他维持着所有的线程和循环,分配很少量的 时间给线程。线程的切换和调度是如此之快,以至于感觉是所有的线程是同步执 行的。 调

7、度是什么意思?调度意味着处理器存储着将要执行完时间的进程的 状态和将来某个时间装载这个进程的状态而恢复其运行。 然而这种方式也有不足 之处,一个线程可以在任何给定的时间中断另外一个线程的执行。假设一个线程 正在向一个文件做写操作,而另外一个线程中断其运行,也向同一个文件做写操 作。Windows 95/NT,UNIX 使用的就是这种线程调度方式。 在非抢占的调度模式下,每个线程可以需要多少时间就占用多 少时间。在这种调度方式下,可能一个执行时间很长的线程使得其他所有需要 的线程“饿死” 。在处理机空闲,即该进程没有使用时,系统可以允 许其他的进程暂时使用。占用的线程拥有对的控制权,只有 它自己

8、主动释放时,其他的线程才可以使用。一些 I/O 和 Windows 3.x 就是使用这种调度策略。 在有些操作系统里面,这两种调度策略都会用到。非抢占的调度策略在线程 运行优先级一般时用到,而对于高优先级的线程调度则多采用抢占式的调度策 略。如果你不确定系统采用的是那种调度策略,假设抢占的调度策略不可用是比 较安全的。在设计应用程序的时候,我们认为那些占用时间比较多的线程 在一定的间隔是会释放的控制权的, 这时候系统会查看那些在等待队列里 面的与当前运行的线程同一优先级或者更高的优先级的线程, 而让这些线程得以 使用。如果系统找到一个这样的线程,就立即暂停当前执行的线程和激活 满足条件的线程。

9、如果没有找到同一优先级或更高级的线程,当前线程还继续占 有。当正在执行的线程想释放的控制权给一个低优先级的线程,当前线程就转入睡眠状态而让低优先级的线程占有。 在多处理器系统,操作系统会将这些独立的线程分配给不同的处理器执行, 这样将会大大的加快程序的运行。线程执行的效率也会得到很大的提高,因为将 线程的分时共享单处理器变成了分布式的多处理器执行。 这种多处理器在三维建 模和图形处理是非常有用的。 需要多线程吗需要多线程吗 我们发出了一个打印的命令,要求打印机进行打印任务,假设这时候计算机 停止了响应而打印机还在工作, 那岂不是我们的停止手上的事情就等着这慢速的 打印机打印?所幸的是,这种情况

10、不会发生,我们在打印机工作的时候还可以同 时听音乐或者画图。因为我们使用了独立的多线程来执行这些任务。你可能会对 多个用户同时访问数据库或者 web 服务器感到吃惊, 他们是怎么工作的?这是因 为为每个连接到数据库或者 web 服务器的用户建立了独立的线程来维护用户的 状态。 如果一个程序的运行有一定的顺序, 这时候采用这种方式可能会出现问题, 甚至导致整个程序崩溃。如果程序可以分成独立的不同的任务,使用多线程,即 使某一部分任务失败了,对其他的也没有影响,不会导致整个程序崩溃。 毫无疑问的是,编写多线程程序使得你有了一个利器可以驾奴非多线程的程 序,但是多线程也可能成为一个负担或者需要不小的

11、代价。如果使用的不当,会 带来更多的坏处。如果一个程序有很多的线程,那么其他程序的线程必然只能占 用更少的时间;而且大量的时间是用于线程调度的;操作系统也需 要足够的内存空间来维护每个线程的上下文信息;因此,大量的线程会降低系统 的运行效率。因此,如果使用多线程的话,程序的多线程必须设计的很好,否则 带来的好处将远小于坏处。因此使用多线程我们必须小心地处理这些线程的创 建,调度和释放工作。 多线程程序设计提示多线程程序设计提示 有多种方法可以设计多线程的应用程序。正如后面的文章所示,我将给出详 细的编程示例,通过这些例子,你将可以更好的理解多线程。线程可以有不同的 优先级,举例子来说,在我们的

12、应用程序里面,绘制图形或者做大量运算的同时 要接受用户的输入,显然用户的输入需要得到第一时间的响应,而图形绘制或者 运算则需要大量的时间,暂停一下问题不大,因此用户输入线程将需要高的优先 级,而图形绘制或者运算低优先级即可。这些线程之间相互独立,相互不影响。 在上面的例子中,图形绘制或者大量的运算显然是需要站用很多的时 间的,在这段时间,用户没有必要等着他们执行完毕再输入信息,因此我们将程 序设计成独立的两个线程,一个负责用户的输入,一个负责处理那些耗时很长的 任务。这将使得程序更加灵活,能够快速响应。同时也可以使得用户在运行的任 何时候取消任务的可能。在这个绘制图形的例子中,程序应该始终负责

13、接收系统 发来的消息。如果由于程序忙于一个任务,有可能会导致屏幕变成空白,这显然 需要我们的程序来处理这样的事件。 所以我必须得有一个线程负责来处理这些消 息,正如刚才所说的应该触发重画屏幕的工作。 我们应该把握一个原则,对于那些对时间要求比较紧迫需要立即得到相应的 任务,我们因该给予高的优先级,而其它的线程优先级应该低于它的优先级。侦 听客户端请求的线程应该始终是高的优先级, 对于一个与用户交互的用户界面的 任务来说,它需要得到第一时间的响应,其优先级因该高优先级。 二二Thread 类类 本节将向大家介绍.NET 中的线程 API,怎么样用 C#创建线程,启动和停止线 程,设置优先级和状态

14、. 在.NET中编写的程序将被自动的分配一个线程.让我们来看看用C#编程语言 创建线程并且继续学习线程的知识。我们都知道.NET 的运行时环境的主线程由 Main ()方法来启动应用程序,而且.NET 的编译程序有自动的垃圾收集功能,这 个垃圾收集发生在另外一个线程里面,所有的这些都是后台发生的,让我们无法 感觉到发生了什么事情。在这里默认的是只有一个线程来完成所有的程序任务, 但是正如我们在第一篇文章讨论过的一样, 有可能我们根据需要自己添加更多的 线程,让程序更好的协调工作。比如说我们的例子中,一个有用户输入的同时需 要绘制图形或者完成大量的运算的程序,我们必须得增加一个线程,让用户的输

15、入能够得到及时的响应,因为输入对时间和响应的要求是紧迫的,而另外一个线 程负责图形绘制或者大量的运算。 .NET 基础类库的 System. Threading 命名空间提供了大量的类和接口支持 多线程。这个命名空间有很多的类,我们将在这里着重讨论 Thread 这个类。 System.Threading.Thread 类是创建并控制线程,设置其优先级并获取其状 态最为常用的类。他有很多的方法,在这里我们将就比较常用和重要的方法做一 下介绍: Thread. Start() :启动线程的执行; Thread.Suspend() :挂起线程,或者如果线程已挂起,则不起作用; Thread.Res

16、ume() :继续已挂起的线程; Thread.Interrupt() :中止处于 Wait 或者 Sleep 或者 Join 线程状态的线程; Thread.Join() :阻塞调用线程,直到某个线程终止时为止 Thread.Sleep() :将当前线程阻塞指定的毫秒数; Thread.Abort() :以开始终止此线程的过程。如果线程已经在终止,则不能通 过 Thread.Start()来启动线程。 Thread. Start() :启动线程的执行; Thread.Suspend() :挂起线程,或者如果线程已挂起,则不起作用; Thread.Resume() :继续已挂起的线程; Thread.Interrupt() :中止处于 Wait 或者 Sleep 或者 Join 线程状态的线程; Thread.Join() :阻塞调用线程,直到某个线程终止时为止 Threa

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 生活休闲 > 科普知识

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号