Description
进程
是操作系统分配资源的最小单位,而 线程
是 CPU 调度的最小单位。通俗的理解,一个应用程序执行的时候,就是一个进程,而这个应用程序里有各种各样的调度,这些调度是通过线程来完成的。例如,当你在电脑里打开 Chrome 浏览器,操作系统就开启了一个进程来运行;这时你又打开了微信客户端,系统就又开启一个进程。我们在几个应用程序来回切换,操作系统通过调度 CPU 在进程间快速的切换,来响应我们的操作。
进程与线程的关系
知乎上有个很形象的举例:
进程就是火车,线程就是火车里一节一节车厢
- 一个进程里可以有多个线程,而一个线程只能属于一个进程
- 不同进程之间数据无法共享,有专门的进程间通信机制;而同一个进程下的线程可以共享资源,因此有个互斥锁的概念:当一个线程访问某块资源时,上锁,其它线程不能访问
- 进程比线程消耗更多的计算机资源,线程则是轻量级的
- 进程使用的内存地址是有限定量的 —— 信号量
操作系统对进程的调度算法
以单核 CPU 为例,进程的调度算法大致有:
先到先得(First-Come-First-Served, FCFS)
轮转
最短进程优先(Shortest Process Next,SPN)
最短剩余时间(Shortest Remaining Time,SRT)
最高响应比优先(Highest Response Ratio Next,HRRN)
反馈法
先到先得(First-Come-First-Served, FCFS)
,按照先来后到,谁先来就先执行。这种作业方式对短进程
和IO 密集进程
不友好,比如有一个长进程正在霸占 CPU 资源,一直把着不放,那短进程就觉得吃亏,因为是按先后顺序排队,久等一会都一样,显然长进程做的事更多。而 IO 进程的话,例如你执行了一个 IO,然后挂起,CPU 资源让出了,等到你 IO 回调回来时,又得重新按顺序去排队,每执行一个 IO 就像蜻蜓点水一样,眨一下就过去了。
轮转
,基于时钟的抢占策略。它的思路是给每一个进程一定的定量执行时间,当时间消耗完毕时,操作系统就会调度其它进程。这种作业方式的难点在于如何确定一个合适的时间分片,如果太长了,相当于一个进程又长时间霸占着 CPU 执行,如果太短了,进程之间的切换需要很高的成本,频繁切换不利于性能。
最短进程优先(Shortest Process Next,SPN)
,听这名字就知道,这种作业方式对短进程
是很友好的。它始终让预估执行时间较短额进程先执行,长进程都靠后执行。它的难点在于操作系统需要评估每个进程的执行时间,比较难确定。它的缺陷在于如果系统有大量的短进程,怎么办呢?这下长进程就会饥饿得不到响应。
最短剩余时间(Shortest Remaining Time,SRT)
,是对最短进程优先
的优化。当一个进程添加到就绪队列时,操作系统会比较新来的进程跟正在执行的进程的 “剩余时间”,让更短的先执行,这意味着新进程可能抢占老进程。它的缺陷在于长进程饥饿问题还是没解决。
最高响应比优先(Highest Response Ratio Next,HRRN)
,总是选择响应比更高的进程先执行,响应比是指:
响应比 = (等待执行时间 + 进程执行时间) / 进程执行时间
这种作业方式可以说兼顾了短进程与长进程的特点,对于短进程,执行时间较短,意味着响应比较高,会优先执行;而对于长进程,它执行时间比较长,一开始响应比比较少,但是随着执行时间越来越长,响应比会不断增加,因此优先级也就越来越高。
反馈法
,进程先执行,事后再来评估它们的优先级。这种作业方式,一开始进程都有相同的优先级,后面假如被抢占(配合其它抢占策略一起用),优先级就会降低一级,所以在执行的过程中,综合多种方式来动态改变它们的优先级。