线程和进程

线程和进程
进程和线程的关系:
(1)一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。
(2)资源分配给进程,同一进程的所有线程共享该进程的所有资源。
(3)CPU分给线程,即真正在CPU上运行的是线程。

1、进程
进程是资源分配的最小单位
进程是程序在计算机上的一次执行活动。是一个具有一定独立功能的程序在某个数据集合的一次运行活动。程序是静态的,进程是动态的。
进程具有的特征:
动态性:进程是程序的一次执行过程,是临时的,有生命期的,是动态产生,动态消亡的;
并发性:任何进程都可以同其他进程一起并发执行;
独立性:进程是系统进行资源分配和调度的一个独立单位;
结构性:进程由程序、数据和进程控制块三部分组成。程序用于描述进程要完成的功能,是控制进程执行的指令集;数据集合是程序在 执行时所需要的数据和工作区;程序控制块(Program Control Block,简称PCB),包含进程的描述信息和控制信息,是进程存在的唯一标志。
2、线程
线程是cup调度的最小单位
线程是进程内的并发,是进程中的一个执行控制单元。
使用线程的好处
1、使用线程可以把占据长时间的程序中的任务放到后台去处理
2、用户界面可以更加吸引人,这样比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度
3、程序的运行速度可能加快
4、在一些等待的任务实现上如用户输入、文件读写和网络收发数据等,使用线程我们可以释放一些珍贵的资源如内存占用等等
3、多进程
同一个时间里,同一个计算机系统中允许两个或两个以上的进程处于并行状态,这是多进程。多进程带来的好处是你可以边听mp3边上网,与此同时甚至可以将下载的文档打印出来,而这些任务之间丝毫不会相互干扰。但并行需要解决的问题是通常并行的进程比CPU数量多得多,而原则上一个CPU只能分配给一个进程(引入线程后,CPU调度的基本单位是线程,进程是资源分配的最小单位),以便运行这个进程。而要让CPU同时运行多个进程,就必须使用并发技术,实现并发技术最常见的就是时间片轮转调度算法,即在操作系统的管理下,所有正在运行的进程轮流使用CPU,每个进程允许占用CPU的时间非常短(比如1毫秒),这样用户根本感觉不出来 CPU是在轮流为多个进程服务,就好象所有的进程都在不间断地运行一样,给用户的感觉就是并行。但实际上在任何一个时间内有且仅有一个进程占有CPU。
4、多线程
一个进程中可以有多条执行路径同时执行,一个线程就是进程中的一条执行路径。
在早期的操作系统中并没有线程的概念,进程是能拥有资源和独立运行的最小单位,也是程序执行的最小单位。它相当于一个进程里只有一个线程,进程本身就是线程。所以线程有时被称为轻量级进程(Lightweight Process,LWP)。后来,随着计算机的发展,对多个任务之间上下文切换的效率要求越来越高,就抽象出一个更小的概念——线程,一般一个进程会有多个(也可是一个)线程。
5、程序和进程比较
程序:code+文档,静态的可执行的二进制文件,未载入内存
进程:程序载入内存,CPU可以调度,程序运行的载体
6、进程和线程比较
1.进程是操作系统分配资源的最小单位,线程是程序执行的最小单位(CPU调度线程)
2.进程是线程的容器,一个进程由一个或多个线程组成,线程是一个进程中代码的不同执行路径
3.进程之间相互独立,但同一进程下的各个线程之间共享程序的内存空间(包括代码段、数据集、堆等)及一些进程级的资源(如打开文件和信号),某进程内的线程在其它进程不可见;
4.调度和切换:线程上下文切换比进程上下文切换要快得多。
7、进程和线程状态
在早期只有进程的操作系统中,进程有五种状态,创建、就绪、运行、阻塞(等待)、退出。早期的进程相当于现在的只有单个线程的进程,那么现在的多线程也有五种状态,现在的多线程的生命周期与早期进程的生命周期类似。
在这里插入图片描述
进程在运行过程有三种状态:就绪、运行、阻塞,创建和退出状态描述的是进程的创建过程和退出过程。

创建:进程正在创建,还不能运行。操作系统在创建进程时要进行的工作包括分配和建立进程控制块表项、建立资源表格并分配资源、加载程序并建立地址空间;

就绪:时间片已用完,此线程被强制暂停,等待下一个属于他的时间片到来;

运行:此线程正在执行,正在占用时间片;

阻塞:也叫等待状态,等待某一事件(如IO或另一个线程)执行完;

退出:进程已结束,所以也称结束状态,释放操作系统分配的资源。
在这里插入图片描述

创建:一个新的线程被创建,等待该线程被调用执行;

就绪:时间片已用完,此线程被强制暂停,等待下一个属于他的时间片到来;

运行:此线程正在执行,正在占用时间片;

阻塞:也叫等待状态,等待某一事件(如IO或另一个线程)执行完;

退出:一个线程完成任务或者其他终止条件发生,该线程终止进入退出状态,退出状态释放该线程所分配的资源。

8、进程死锁
两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。

8.1 死锁的发生必须具备以下四个必要条件:

(1)互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。

(2)占用并等待条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。

(3)不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。

(4)环路等待条件:指在发生死

锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2, …… ,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,…… ,Pn正在等待已被P0占用的资源。

8.2 处理死锁的方法

(1) 预防死锁:这是一种较简单和直观的事先预防的方法。方法是通过设置某些限制条件,去破坏产生死锁的四个必要条件中的一个或者几个,来预防发生死锁。预防死锁是一种较易实现的方法,已被广泛使用。但是由于所施加的限制条件往往太严格,可能会导致系统资源利用率和系统吞吐量降低。

(2) 避免死锁:该方法同样是属于事先预防的策略,但它并不须事先采取各种限制措施去破坏产生死锁的的四个必要条件,而是在资源的动态分配过程中,用某种方法去防止系统进入不安全状态,从而避免发生死锁。

(3)检测死锁:这种方法并不须事先采取任何限制性措

施,也不必检查系统是否已经进入不安全区,此方法允许系统在运行过程中发生死锁。但可通过系统所设置的检测机构,及时地检测出死锁的发生,并精确地确定与死锁有关的进程和资源,然后采取适当措施,从系统中将已发生的死锁清除掉。

(4)解除死锁:这是与检测死锁相配套的一种措施。当检测到系统中已发生死锁时,须将进程从死锁状态中解脱出来。常用的实施方法是撤销或挂起一些进程,以便回收

一些资源,再将这些资源分配给已处于阻塞状态的进程,使之转为就绪状态,以继续运行。死锁的检测和解除措施,有可能使系统获得较好的资源利用率和吞吐量,但在实现上难度也最大。

8.3 死锁的预防

因为独占资源必须以互斥方式进行访问,所以要预防死锁只能从破坏后三个条件下手了。

(1)破坏占有并等待条件:要破坏这个条件,就要求每个进程必须一次性的请求它们所需要的所有资源,若无法全部获取就等待,直到满足为止,也可以采用事务机制,确保可以回滚,即把获取、释放资源做成原子性的。这个方法实现起来可能会比较困难,因为某些情况下,进程并不能事先直到自己需要哪些资源,也有时候并不需要分配到所有资源就可以运行。

(2)破坏不可剥夺条件:一个已占有资源的进程若要再申请新的资源,它必须先释放已占有的资源。若随后再需要这些资源,需要重新申请。

(3)破坏循环等待条件:将系统中所有的资源设置标志位、排序,规定所有的进程申请资源必须以一定的顺序(升序或降序)做操作。

8.4 死锁的避免

死锁的预防是通过破坏产生条件来阻止死锁的产生,但这种方法破坏了系统的并行性和并发性。死锁产生的前三个条件是死锁产生的必要条件,也就是说要产生死锁必须具备的条件,而不是存在这3个条件就一定产生死锁,那么只要在逻辑上回避了第四个条件就可以避免死锁。避免死锁采用的是允许前三个条件存在,但通过合理的资源分配算法来确保永远不会形成环形等待的封闭进程链,从而避免死锁。该方法支持多个进程的并行执行,为了避免死锁,系统动态的确定是否分配一个资源给请求的进程。方法如下:

(1)如果一个进程的当前请求的资源会导致死锁,系统拒绝启动该进程;

(2)如果一个资源的分配会导致下一步的死锁,系统就拒绝本次的分配;

显然要避免死锁,必须事先知道系统拥有的资源数量及其属性。

9、windows环境举例
查看进程和线程:

在“进程”选项卡“线程数”显示列,我们可以看到一个应用程序包含的线程数。如果一个应用程序有多个进程,我们能看到每一个进程,如在上图中,VisualSVNServer(SVN服务器)就有多个进程。同时,如果打开了一个应用程序的多个实例也会有多个进程,如下图打开了两个cmd窗口,就有两个cmd进程。

有时候,你打开一个程序,稍等一会,这个程序运行了,但是,它的主界面窗口变灰了,标题栏上写了“应用程序没有响应”这样的字样。这个时候,这个程序到底发生了什么呢?
这个程序由很多线程组成,负责后台处理数据的线程在不停的使用操作系统分配给这个应用程序的处理器时间,而负责 GUI 的线程得不到处理器时间,从而导致窗口变灰”失去响应“。稍等一会后,这个程序的窗口又恢复了,”失去响应”字样消失了,又能正常操作这个应用程序了。这个时候,因为负责GUI的线程得到了处理器时间,它才能够响应用户对它的操作。

10、用多进程还是多线程编程
对比维度

多进程

多线程

总结

数据共享、同步

数据共享复杂,需要用IPC;数据是分开的,同步简单

因为共享进程数据,数据共享简单,但也是因为这个原因导致同步复杂

各有优势

内存、CPU

占用内存多,切换复杂,CPU利用率低

占用内存少,切换简单,CPU利用率高

线程占优

创建销毁、切换

创建销毁、切换复杂,速度慢

创建销毁、切换简单,速度很快

线程占优

编程、调试

编程简单,调试简单

编程复杂,调试复杂

进程占优

可靠性

进程间不会互相影响

一个线程挂掉将导致整个进程挂掉

进程占优

分布式

适应于多核、多机分布式;如果一台机器不够,扩展到多台机器比较简单

适应于多核分布式

进程占优

1)需要频繁创建销毁的优先用线程

这种原则最常见的应用就是Web服务器了,来一个连接建立一个线程,断了就销毁线程,要是用进程,创建和销毁的代价是很难承受的

2)需要进行大量计算的优先使用线程

所谓大量计算,当然就是要耗费很多CPU,切换频繁了,这种情况下线程是最合适的。这种原则最常见的是图像处理、算法处理。

3)强相关的处理用线程,弱相关的处理用进程

什么叫强相关、弱相关?理论上很难定义,给个简单的例子就明白了。

一般的Server需要完成如下任务:消息收发、消息处理。“消息收发”和“消息处理”就是弱相关的任务,而“消息处理”里面可能又分为“消息解码”、“业务处理”,这两个任务相对来说相关性就要强多了。因此“消息收发”和“消息处理”可以分进程设计,“消息解码”、“业务处理”可以分线程设计。当然这种划分方式不是一成不变的,也可以根据实际情况进行调整。

4)可能要扩展到多机分布的用进程,多核分布的用线程

5)都满足需求的情况下,用你最熟悉、最拿手的方式

至于“数据共享、同步”、“编程、调试”、“可靠性”这几个维度的所谓的“复杂、简单”应该怎么取舍,我只能说:没有明确的选择方法。但我可以告诉你一个选择原则:如果多进程和多线程都能够满足要求,那么选择你最熟悉、最拿手的那个。

需要提醒的是:虽然我给了这么多的选择原则,但实际应用中基本上都是“进程+线程”的结合方式,千万不要真的陷入一种非此即彼的误区。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值