进程与线程杂谈(一)
来源:百度文库 编辑:神马文学网 时间:2024/04/25 14:35:51
本站原创:Null
我了解不多,只能说说80x86上的Windows环境,其他如Alpha,Mac或者Linux,
我就一窍不通了,见笑见笑……
现代操作系统都是多任务的操作系统,在这里要澄清一个概念,Windows 3.x时代也
有所谓的多任务,但是,那并不是现代意义的多任务--"抢占式多任务"。Windows 3.x的
多任务是非抢占式的,即,一个应用程序,甚至系统,要等现在正在运行的程序主动放弃
CPU(程序员把这个礼貌的行为写到程序中),才能获得执行时间片。可以看出,在这种环
境中,操作系统的主动性是很小的,只要某个已经获得CPU的程序不主动放弃CPU,操作
系统就得不到时间运行,亦无法实行其管理调度功能。如果一个应用程序因崩溃而挂起,
将导致整个系统挂起。
而抢占式的多任务是指,将CPU时间片分配最需要它的应用程序,即便一个应用程序永
远不打算放弃CPU,操作系统也能保证随时"抢占"CPU时间,然后对当前所有的任务进行
合理的调度。
要实现多任务,首先要有CPU的支持,80x86 (Alpha?我不懂,别问我……) 支持
多任务,通过一个TSS--任务描述符,80x86能够描述一个任务。详细我就不说了,和本
文关系不大,只要说明抢占式多任务不是操作系统在单干就行了。
作为操作系统,要能够利用CPU提供的功能才能实现多任务,Windows做到了这点(当
然,Linux也做到了,只是我不懂……)。系统有一个核心调度程序,负责为每一个任务分配
CPU时间,允许其执行指定的一段时间,当这段时间用完后,控制权会重新交回到操作系统,
操作系统可在此时重新分配CPU时间。至于CPU时间是如何分配的,就又不是本文的范围了。
Microsoft给出的文档是说"系统保证CPU时间的分配是公平的",仅此而已……。
在Windows中,一个任务就是一个线程,以前曾经说过,线程不能没有存储而存在,
而其所依赖存在的存储对象就是进程。而一个进程--以前也说过了--对应一个映象(可执行
文件)。也就是说,在一个可执行文件运行时,可以有多个线程。
好了,基本的概念大概说明了,来讨论一下它们的用途。要这些多出来(除了原始线程
外)的线程有什么用?MSDN给出的答案是"等"。但我个人认为稍微笼统了一点(偏激一点?
)。不过,至少,有一点是肯定的--绝不要使多个线程同时进行繁重的操作--除非你是建立
了CPU数目个线程(32路对等处理器系统?)。无论如何,实际工作的还是CPU,在这种情
况下,CPU不仅不会少执行指令,还要执行很多的排班程序指令以及任务的切换指令--反而
降低效率。
在需要等待的地方,多线程确实能够发挥很高的效能。(注意,并不一定是最高,以后
将说到经常是更好的实现方法,这里只是说明线程的用法)举一个例子:一个网络程序向远
程主机发送了一个请求,正在等待回应,而在此期间,它还希望能够与用户进行交互。一种
实现方法是:程序继续与用户交互,在交互的间歇检查一下回应是否到达。而更好的方法是
建立一个新的线程(称为工作线程)来等待回应,原始线程继续照常与用户交互。如果您已
经感觉到后一种方法确实比前一种方法好很多,那么,您可以不读下一段,不用听我罗嗦了。
后一种方法比前一种方法好在后者执行的指令更少,因而效率更高。如果您对Windows
编程熟悉:在实现前者时,必须保证能够及时检测到回应到达,因而就不能使用GetMessage()
而要使用PeekMessage()。如果使用GetMessage(),而恰巧在很长的一段时间内都没
有消息到达,原始线程就不会从GetMessage()返回,也就不能检测回应是否到达。使用
PeekMessage(),可以令其在没有消息时也立即返回,因而可以检测回应是否到达。网络
部分的情况也一样--程序不能等回应一直等下去否则就无法与用户交互。无论如何,在即没
有消息、也没有回应到达的情况下,原始线程没有有效的进入等待状态,而是不停地"空转",
检测二者中是否有到达的,这对系统资源显然是极大的浪费。而对于后者,原始线程通过
GetMessage()有效的进入了等待,工作线程也可以通过类似的方法进入等待,例如使用
Socket的select()。
但是,新的问题又出现了,工作线程发现回应已经到达了,它可能要通知原始线程才行
--它与原始线程是并发执行的。这就涉及到线程简通信了,有一种最简单的方法:Windows
消息。工作线程通过向原始线程的窗口发送一个消息,然后终止;当原始线程的消息循环发
现这个消息时,就知道回应已经到达了。线程间通信的方法还有很多,将在以后专门介绍。
最后要说明的是--很重要的一点:多线程经常不是程序员主动来使用的,而是在依赖操
作系统时,已然是多线程了。即使用,也很有节制,滥用线程将适得其反。究竟什么地方应
该使用多线程,并没有什么规则,将多线程用在该用的地方而已,当然不会刻意的使用它。
当综合各种条件和各种可能的方案后,如发现多线程是最好的,就是使用多线程的最佳时机。
我是否说的是废话?呵呵,其实就像这篇文章一样,我也很头疼,线程是在遇到实际需要时
才想起用的,硬要设计一种情况来使用实在不易。有备无患。多线程不是杀手锏,但是掌握
它是向较高级编程迈进的必经之路。
我了解不多,只能说说80x86上的Windows环境,其他如Alpha,Mac或者Linux,
我就一窍不通了,见笑见笑……
现代操作系统都是多任务的操作系统,在这里要澄清一个概念,Windows 3.x时代也
有所谓的多任务,但是,那并不是现代意义的多任务--"抢占式多任务"。Windows 3.x的
多任务是非抢占式的,即,一个应用程序,甚至系统,要等现在正在运行的程序主动放弃
CPU(程序员把这个礼貌的行为写到程序中),才能获得执行时间片。可以看出,在这种环
境中,操作系统的主动性是很小的,只要某个已经获得CPU的程序不主动放弃CPU,操作
系统就得不到时间运行,亦无法实行其管理调度功能。如果一个应用程序因崩溃而挂起,
将导致整个系统挂起。
而抢占式的多任务是指,将CPU时间片分配最需要它的应用程序,即便一个应用程序永
远不打算放弃CPU,操作系统也能保证随时"抢占"CPU时间,然后对当前所有的任务进行
合理的调度。
要实现多任务,首先要有CPU的支持,80x86 (Alpha?我不懂,别问我……) 支持
多任务,通过一个TSS--任务描述符,80x86能够描述一个任务。详细我就不说了,和本
文关系不大,只要说明抢占式多任务不是操作系统在单干就行了。
作为操作系统,要能够利用CPU提供的功能才能实现多任务,Windows做到了这点(当
然,Linux也做到了,只是我不懂……)。系统有一个核心调度程序,负责为每一个任务分配
CPU时间,允许其执行指定的一段时间,当这段时间用完后,控制权会重新交回到操作系统,
操作系统可在此时重新分配CPU时间。至于CPU时间是如何分配的,就又不是本文的范围了。
Microsoft给出的文档是说"系统保证CPU时间的分配是公平的",仅此而已……。
在Windows中,一个任务就是一个线程,以前曾经说过,线程不能没有存储而存在,
而其所依赖存在的存储对象就是进程。而一个进程--以前也说过了--对应一个映象(可执行
文件)。也就是说,在一个可执行文件运行时,可以有多个线程。
好了,基本的概念大概说明了,来讨论一下它们的用途。要这些多出来(除了原始线程
外)的线程有什么用?MSDN给出的答案是"等"。但我个人认为稍微笼统了一点(偏激一点?
)。不过,至少,有一点是肯定的--绝不要使多个线程同时进行繁重的操作--除非你是建立
了CPU数目个线程(32路对等处理器系统?)。无论如何,实际工作的还是CPU,在这种情
况下,CPU不仅不会少执行指令,还要执行很多的排班程序指令以及任务的切换指令--反而
降低效率。
在需要等待的地方,多线程确实能够发挥很高的效能。(注意,并不一定是最高,以后
将说到经常是更好的实现方法,这里只是说明线程的用法)举一个例子:一个网络程序向远
程主机发送了一个请求,正在等待回应,而在此期间,它还希望能够与用户进行交互。一种
实现方法是:程序继续与用户交互,在交互的间歇检查一下回应是否到达。而更好的方法是
建立一个新的线程(称为工作线程)来等待回应,原始线程继续照常与用户交互。如果您已
经感觉到后一种方法确实比前一种方法好很多,那么,您可以不读下一段,不用听我罗嗦了。
后一种方法比前一种方法好在后者执行的指令更少,因而效率更高。如果您对Windows
编程熟悉:在实现前者时,必须保证能够及时检测到回应到达,因而就不能使用GetMessage()
而要使用PeekMessage()。如果使用GetMessage(),而恰巧在很长的一段时间内都没
有消息到达,原始线程就不会从GetMessage()返回,也就不能检测回应是否到达。使用
PeekMessage(),可以令其在没有消息时也立即返回,因而可以检测回应是否到达。网络
部分的情况也一样--程序不能等回应一直等下去否则就无法与用户交互。无论如何,在即没
有消息、也没有回应到达的情况下,原始线程没有有效的进入等待状态,而是不停地"空转",
检测二者中是否有到达的,这对系统资源显然是极大的浪费。而对于后者,原始线程通过
GetMessage()有效的进入了等待,工作线程也可以通过类似的方法进入等待,例如使用
Socket的select()。
但是,新的问题又出现了,工作线程发现回应已经到达了,它可能要通知原始线程才行
--它与原始线程是并发执行的。这就涉及到线程简通信了,有一种最简单的方法:Windows
消息。工作线程通过向原始线程的窗口发送一个消息,然后终止;当原始线程的消息循环发
现这个消息时,就知道回应已经到达了。线程间通信的方法还有很多,将在以后专门介绍。
最后要说明的是--很重要的一点:多线程经常不是程序员主动来使用的,而是在依赖操
作系统时,已然是多线程了。即使用,也很有节制,滥用线程将适得其反。究竟什么地方应
该使用多线程,并没有什么规则,将多线程用在该用的地方而已,当然不会刻意的使用它。
当综合各种条件和各种可能的方案后,如发现多线程是最好的,就是使用多线程的最佳时机。
我是否说的是废话?呵呵,其实就像这篇文章一样,我也很头疼,线程是在遇到实际需要时
才想起用的,硬要设计一种情况来使用实在不易。有备无患。多线程不是杀手锏,但是掌握
它是向较高级编程迈进的必经之路。
进程与线程杂谈(一)
进程与线程杂谈(一)
线程与进程
进程与线程的区别
进程和线程
进程和线程
进程和线程
进程和线程
Java笔记(六 程序、进程和线程)
linux 线程 进程经典文章
进程和线程的区别
linux 线程 进程经典文章
进程和线程的区别
进程和线程的区别
进程和线程的区别
【原创】技术系列之 线程(一)
linux 线程 进程经典文章2
任务、进程和线程的区别
性能测试-根据Loadrunner官方说明来解释Vu的进程与线程区别 -小测天下-搜狐博客
[经济杂谈]资本、官僚与改革(一)pp
【原创】技术系列之 线程(一) - CppExplore - C 博客
共享内存与线程局部存储(转载)
Linux环境进程间通信(一)
vc中如何调用webservice? VC/MFC / 进程/线程/DLL