这一次,彻底搞懂进程与线程之间的联系

什么是进程?

进程是系统进行资源调度和分配的基本单位,每个进程都有自己独立的一块内存空间,在Windows系统中,一个运行的exe程序就是一个进程。

什么是线程?

线程是进程的子任务,是CPU调度和分配的基本单位,用于保证程序的实时性,实现进程内部的并发,线程是操作系统可以识别的最小执行和调度单位,线程之间共享同一块地址空间。

进程和线程的区别

  • 根本区别:进程是操作系统进行资源调度和分配的基本单位,而线程是CPU进行资源调度和分配的基本单位。
  • 从资源开销上讲:每个进程都有自己的内存空间,进程之间切换性能开销比较大,线程与线程之间是共享代码和内存空间的,每个线程都有自己独立的运行栈和程序计数器,线程之间的开销小。
  • 从包含关系上讲:一个进程可以有多个线程,线程是进程的一部分。
  • 从内存分配上讲:同一进程的线程共享本进程的地址空间和资源,而进程之间的地址空间和资源是相互独立的。
  • 从影响关系上讲:一个进程崩溃后,在保护模式下不会对其他进程产生影响,但是一个线程崩溃整个进程都会挂掉,所以多进程程序相对多线程要更加健壮。
  • 从执行过程上讲:进程可以独立执行,但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制,两者均可并发执行。

并发和并行的区别

  • 并发:一个处理器同时处理多个任务。类似于两队等一个咖啡机。
  • 并行:多个处理器或者多核处理器同时处理多个不同的任务,类似于两队等待两个咖啡机。

进程之间如何进行通信?

  1. 消息队列

比如A进程想要给B进程发送消息,A进程把数据放在对应的消息队列之后就可以返回了,B进程需要的时候去消息队列中读取数据即可,同理,B进程要给A进程发送消息也是如此。消息队列是保存在内核中的消息链表。

  1. 共享内存

共享内存的机制就是拿出一块虚拟地址空间来,映射到相同的物理内存中,这样一个进程写入的文件,另一个进程马上就可以看到,减少了拷贝的次数,提高了进程之间通信的速度。

  1. Socket通信

Socket不仅可以实现跨网络和不同主机之间的进程通信,还可以在同主机上进行进程通信。

线程之间如何进行通信?

线程间通信的目的主要是用于线程同步,主要有以下几种机制:

  • 锁机制:互斥锁、读写锁等。
  • 信号量机制
  • 阻塞唤醒机制

进程调度策略

  1. 先来先服务
  2. 最短作业优先调度
  3. 时间片轮转调度(给每个进程分配一个时间片,CPU轮流切换进程执行。)
  4. 最高优先级调度(在时间片轮转的基础上,加上了优先级,调度程既希望给每个进程轮转调度,又希望每次轮转尽可能选择高优先级的进程)

常见问题汇总

RQ1:什么是僵尸进程?

僵尸进程指的是子进程比父进程先结束,而父进程没有回收子进程,释放子进程占用的资源,此时子进程将成为一个僵尸进程。僵尸进程会占用系统资源,如果很多,则会严重影响服务器的性能。

RQ2:Chrome浏览器为什么采用多进程架构?

浏览器刚被设计出来的时候,网页资源占有率比较小,因此一个进程处理多个网页是可行的,但是随着流媒体资源的丰富,网页也变得越来越复杂,把所有网页都放在一个进程在健壮性、响应速度、安全性方面都面临很多挑战,如果是多线程架构,一个网页崩溃会导致其他网页受到影响。多线程架构之间的内存共享也会带来安全问题。

RQ3:浏览器的不同tab间是线程还是进程?

对Chrome浏览器来说不同的tab是不同的进程。

RQ4:浏览器都有哪些进程事件?

  1. Browser进程:浏览器的主线程,负责浏览器界面的显示与交互,各个页面的管理,创建和销毁其他进程,网络资源的管理和下载等。
  2. Renderer进程:也称为浏览器渲染进程或浏览器内核,其内部是多线程的,主要负责页面渲染,脚本执行,事件处理等。
  3. 第三方插件进程。
  4. GPU进程:用于3D绘制等。

RQ5:浏览器内核都有哪些线程?

  • GUI渲染线程
  • JS引擎线程
  • 定时触发器线程
  • 事件触发线程
  • 异步http请求线程

RQ5:浏览器处理AJAX请求和渲染页面是同一个进程吗,为什么?

浏览器处理Ajax请求是发生在浏览器内核进程中的异步http请求线程中,GUI渲染也是在内核中,所以他们在同一个进程中,但是不是同一个线程。

RQ6:浏览器的Worker线程和主线程是如何进行通信的?

  1. 主线程采用new命令,调用Worker()新建一个Worker线程。Worker()构造函数的参数是一个脚本文件,该文件就是Worker线程所要执行的任务。
  2. 主线程调用woker.postmessage方法想worker发送消息。
  3. worker线程通过监听函数onmessage收到消息,处理数据然后通过postmessage进行返回。
  4. 主线程通过decodeWorker.onmessage监听函数,接收子线程发回来的消息。
  5. 等Worker完成任务后,主线程就可以把它关掉了。

猜你喜欢

转载自blog.csdn.net/sinat_41696687/article/details/123458338