进程与线程

来源:互联网 发布:用python生成随机文件 编辑:程序博客网 时间:2024/06/06 09:02

简而言之,一个程序至少有一个进程,一个进程至少有一个线程. 
线程的划分尺度小于进程,使得多线程程序的并发性高。
另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.
一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行.

进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。


一个线程包含以下内容。

  • 一个指向当前被执行指令的指令指针;
  • 一个栈;
  • 一个寄存器值的集合,定义了一部分描述正在执行线程的处理器状态的值;
  • 一个私有的数据区。

所有这些元素都归于线程执行上下文的名下。处在同一个进程中的所有线程都可以访问该进程所包含的地址空间,当然也包含存储在该空间中的所有资源。


进程与线程

进程(process)是一块包含了某些资源的内存区域。操作系统利用进程把它的工作划分为一些功能单元。

进程中所包含的一个或多个执行单元称为线程(thread)。进程还拥有一个私有的虚拟地址空间,该空间仅能被它所包含的线程访问。


进程和线程是两个相对的概念,通常来说,一个进程可以定义程序的一个实例(Instan
ce)。在Win32中,进程并不执行什么,它只是占据应用程序所使用的地址空间。为了让
进程完成一定的工作,进程必须至少占有一个线程,正是这个线程负责包含进程地址空
间中的代码。实际上,一个进程可以包含几个线程,它们可以同时执行进程地址空间中
的代码。为了做到这一点,每个线程有自己的一组CPU寄存器和堆栈。每个进程中至少有
一个线程在执行其地址空间中的代码。如果没有线程执行进程地址空间中的代码,进程
也就没有继续存在的理由,系统将自动清除进程及其地址空间。
多线程的实现原理
创建一个进程时,它的第一个线程称为主线程(Primary   thread),由系统自动生成。
然后可以由这个主线程生成额外的线程,而这些线程,又可以生成更多的线程。
在运行一个多线程的程序时,从表面上看,这些线程似乎在同时运行。而实际情况并非
如此,为了运行所有的这些线程,操作系统为每个独立线程安排一些CPU时间。单CPU操
作系统以轮转方式向线程提供时间片(Quantum),每个线程在使用完时间片后交出控制
,系统再将CPU时间片分配给下一个线程。由于每个时间片足够的短,这样就给人一种假
象,好像这些线程在同时运行。创建额外线程的唯一目的就是尽可能地利用CPU时间。
多线程的问题
使用多线程编程可以给程序员带来很大的灵活性,同时也使原来需要复杂技巧才能解决
的问题变得容易起来。但是,不应该人为地将编写的程序分成一些碎片,让这些碎片按
各自的线程执行,这不是开发应用程序的正确方法。
线程很有用,但当使用线程时,可能会在解决老问题的同时产生新问题。例如要开发一
个字处理程序,并想让打印功能作为单独的线程自己执行。这听起来是很好的主意,因
为在打印时,用户可立即返回,开始编辑文档。但这样一来,在该文档被打印时文档中
的数据就有可能被修改,打印的结果就不再是所期望的内容。也许最好不要把打印功能
放在单独的线程中,不过如果一定要用多线程的话,也可以考虑用下面的方法解决:第
一种方法是锁定正在打印的文档,让用户编辑其他的文档,这样在结束打印之前,该文
档不会作任何修改;另一个方法可能更有效一些,即可以把该文档拷贝到一个临时文件
中,打印这个临时文件的内容,同时允许用户对原来的文档进行修改。当包含文档的临
时文件打印完成时,再删去这个临时文件。
通过上面的分析可以看出,多线程在帮助解决问题的同时也可能带来新问题。因此有必
要弄清楚,什么时候需要创建多线程,什么时候不需要多线程。总的来说,多线程往往
用于在前台操作的同时还需要进行后台的计算或逻辑判断的情况,而对于GUI(图形用户
接口),除了开发MDI(多文档界面)应用程序外,应尽量不使用多线程。
线程的分类
在MFC中,线程被分为两类,即工作线程和用户界面线程。如果一个线程只完成后台计算
,不需要和用户交互,那么可以使用工作线程;如果需要创建一个处理用户界面的线程
,则应使用用户界面线程。这两者的主要区别在于,MFC框架会给用户界面线程增加一个
消息循环,这样用户界面线程就可以处理自己消息队列中的消息。这样看来,如果需要
在后台作一些简单的计算(如对电子表格的重算),则首先应考虑使用工作线程,而当
后台线程需要处理比较复杂的任务,确切地说,当后台线程的执行过程会随着实际情况
的不同而改变时,就应该使用用户界面线程,以便能对不同的消息作出响应。
线程的优先级
当系统需要同时执行多个进程或多个线程时,有时会需要指定线程的优先级。线程的优
先级一般是指这个线程的基优先级,即线程相对于本进程的相对优先级和包含此线程的
进程的优先级的结合。操作系统以优先级为基础安排所有的活动线程,系统的每一个线
程都被分配了一个优先级,优先级的范围从0到31。运行时,系统简单地给第一个优先级
为31的线程分配CPU时间,在该线程的时间片结束后,系统给下一个优先级为31的线程分
配CPU时间。当没有优先级为31的线程时,系统将开始给优先级为30的线程分配CPU时间
,以此类推。除了程序员在程序中改变线程的优先级外,有时程序在执行过程中系统也
会自动地动态改变线程的优先级,这是为了保证系统对终端用户的高度响应性。比如用
户按了键盘上的某个键时,系统就会临时将处理WM_KEYDOWN消息的线程的优先级提高2到
3。CPU按一个完整的时间片执行线程,当时间片执行完毕后,系统将该线程的优先级减
1。
线程的同步
在使用多线程编程时,还有一个非常重要的问题就是线程同步。所谓线程同步是指线程
之间在相互通信时避免破坏各自数据的能力。同步问题是由前面说到的Win32系统的CPU
时间片分配方式引起的。虽然在某一时刻,只有一个线程占用CPU(单CPU时)时间,但
是没有办法知道在什么时候,在什么地方线程被打断,这样如何保证线程之间不破坏彼
此的数据就显得格外重要。在MFC中,可以使用4个同步对象来保证多线程同时运行。它
们分别是临界区对象(CCriticalSection)、互斥量对象(CMutex)、信号量对象(CS
emaphore)和事件对象(CEvent)。在这些对象中,临界区对象使用起来最简单,它的
缺点是只能同步同一个进程中的线程。另外,还有一种基本的方法,本文称为线性化方
法,即在编程过程中对一定数据的写操作都在一个线程中完成。这样,由于同一线程中

的代码总是按顺序执行的,就不可能出现同时改写数据的情况。


多线程处理的优点

同步应用程序的开发比较容易,但由于需要在上一个任务完成后才能开始新的任务,所以其效率通常比多线程应用程序低。如果完成同步任务所用的时间比预计时间长,应用程序可能会不响应。多线程处理可以同时运行多个过程。例如,文字处理器应用程序在您处理文档的同时,可以检查拼写(作为单独的任务)。由于多线程应用程序将程序划分成独立的任务,因此可以在以下方面显著提高性能: 
多线程技术使程序的响应速度更快,因为用户界面可以在进行其他工作的同时一直处于活动状态。 
当前没有进行处理的任务可以将处理器时间让给其他任务。 
占用大量处理时间的任务可以定期将处理器时间让给其他任务。 
可以随时停止任务。 
可以分别设置各个任务的优先级以优化性能。 

是否需要创建多线程应用程序取决于多个因素。在以下情况下,最适合采用多线程处理: 
耗时或大量占用处理器的任务阻塞用户界面操作。 
各个任务必须等待外部资源(如远程文件或 INTERNET 连接)。 

例如,用于跟踪 WEB 页上的链接并下载满足特定条件的文件的 INTERNET 应用程序“ROBOT”。这种应用程序可以依次同步下载各个文件,也可以使用多线程同时下载多个文件。多线程方法比同步方法的效率高很多,因为即使在某些线程中远程 WEB 服务器的响应非常慢,也可以下载文件。

坏处:增加了调度和管理的开销,带来了一些不确定性,需要复杂的同步机制,避免死锁等等。
好处:一定程度上提高响应速度,在多核的情况下还是更能充分利用CPU资源的。

=====================================================================================

单线程的也就是程序执行时,所跑的程序路径(处理的东西)是连续顺序下来的,必须前面的处理好,后面的才会执行到。   
(未细看)单线程和多线程的优缺点 - Daniel - 休子的博客       多线程嘛,举个例子也就是说程序可以同时执行2个以上相同类似的操作,比如一些搜索代理或者群发email的多线程软件,由于操作一次需要网络的返回信息   花的时间比较长,而对cpu来说却是空闲的,如果是一个一个顺序执行,那么搜索几千个IP就会花上好久好久。   而如果用多线程就可以在等待期间   加入其他的搜索,然后等待,这样可以提高效率。不过多线程和多进程公用一些资源时要考虑的问题好像也是一样的,对于一些公共资源或者公共变量的访问和修改时要注意特别的,需要一些锁定什么的,还有顺序问题的考虑。  
       多线程编程的目的,就是"最大限度地利用CPU资源",当某一线程的处理不需要占用CPU而只和I/O,OEMBIOS等资源打交道时,让需要占用CPU资源的其它线程有机会获得CPU资源。每个程序执行时都会产生一个进程,而每一个进程至少要有一个主线程。这个线程其实是进程执行的一条线索,除了主线程外你还可以给进程增加其它的线程,也即增加其它的执行线索,由此在某种程度上可以看成是给一个应用程序增加了多任务功能。当程序运行后,您可以根据各种条件挂起或运行这些线程,尤其在多CPU的环境中,这些线程是并发运行的。多线程就是在一个进程内有多个线程。从而使一个应用程序有了多任务的功能。多进程技术也可以实现这一点,但是创建进程的高消耗(每个进程都有独立的数据和代码空间),进程之间通信的不方便(消息机制),进程切换的时间太长,这些导致了多线程的提出,对于单CPU来说(没有开启超线程),在同一时间只能执行一个线程,所以如果想实现多任务,那么就只能每个进程或线程获得一个时间片,在某个时间片内,只能一个线程执行,然后按照某种策略换其他线程执行。由于时间片很短,这样给用户的感觉是同时有好多线程在执行。但是线程切换是有代价的,因此如果采用多进程,那么就需要将线程所隶属的该进程所需要的内存进行切换,这时间代价是很多的。而线程切换代价就很少,线程是可以共享内存的。所以采用多线程在切换上花费的比多进程少得多。但是,线程切换还是需要时间消耗的,所以采用一个拥有两个线程的进程执行所需要的时间比一个线程的进程执行两次所需要的时间要多一些。即采用多线程不会提高程序的执行速度,反而会降低速度,但是对于用户来说,可以减少用户的响应时间。上述结果只是针对单CPU,如果对于多CPU或者CPU采用超线程技术的话,采用多线程技术还是会提高程序的执行速度的。因为单线程只会映射到一个CPU上,而多线程会映射到多个CPU上,超线程技术本质是多线程硬件化,所以也会加快程序的执行速度。

====================================================================================

如果线程出现死锁,唯一能证明的就是应用程序有问题,这并不是线程的缺点。

线程相对于进程的优点:
1、开销小
2、资源共享性好。

线程相对于进程的缺点:
1、共享资源需要耗费一定的锁资源,同步相对复杂。
2、一个线程崩溃可能导致整个进程崩溃,这个当然是自己的应用程序有问题

====================================================================================

CPU是以时间片的方式为进程分配CUP处理时间的,当一个进程以同步的方式去完成几件事情时,此进程必须完成了第一件事情以后再做第二件事,如此按顺序地向CPU请求完成要做的事情。在此单线程的工作模式下,如果把CUP看作是一共有100个时间片的话,CPU可能一直都只是花了其中的10个时间片来处理当前进程所要做的事情,只是用到了CPU的10%的时间片,而其他时间都白白浪费了,当然,实际上CPU的工作模式还是做完一件事以后再去做另一件事,只是CUP的处理速度非常快,很快就处理完成所请求的情事。

    为了提高CPU的使用率,采用多线程的方式去同时完成几件事情而互不干扰,如当前进程要完成三件事情1、2、3,那么CPU会分别用10%的时间来同时处理这3件事情,从而让CPU的使用率达到了30%,大大地提高了CPU的利用率。多线程的好处在处理一些特殊的场合其优势尤其明显。比如下载文件,你要一边下载一边显示进度一边保存,在这种情况下,如果没有用多线程的话,没有意外的话一般都会把主线程阻塞,比如进度条的进度根本没有随着已下载的量而变化,堪至是整个窗体都动不了,用多线程就可以很好地解决这个问题。

    这里有一个生活实例可能更好地去理解多线程:回去看你女朋友做饭,正常的话她都会把洗好的菜(肉)先放到锅里煮,然后一边洗别的菜或处理别的事情,如:洗碗、收拾桌台准备开饭,人还是一个人,但她同时做几件事情,这样就可以大大地提高效率。总的一句话就是:CPU还是要花同样多的时间去完成所有的事情,但多线程可以让CPU掺插地同时做多件事情,在视觉上让用户觉得计算机在同时帮他处理多件事情,更好地改善用户体验。

    了解了多线程的好处以后,就要了解应该在什么样的情况下使用多线程技术。因为并不是说所有情况下用多线程都是好事,因为多线程的情况下,CPU还要花时间去维护,CPU处理各线程的请求时在线程间的切换也要花时间,所以一般情况下是可以不用多线程的,用了有时反而会得不偿失。大多情况下,要用到多线程的主要是需要处理大量的IO操作时或处理的情况需要花大量的时间等等,比如:读写文件、视频图像的采集、处理、显示、保存等。


原创粉丝点击