◆

进程与线程、浏览器多进程与 JS Event Loop

2023-02-02 01:370

进程与线程

  • 进程:是 cpu 资源分配的最小单位,是能拥有资源和独立运行的最小单位。拥有独立的地址空间。
  • 线程:是 cpu 调度的最小单位,安排 CPU 执行的最小单位。同一个进程下的所有线程,共享进程的地址空间。(线程是建立在进程的基础上的一次程序运行单位,一个进程中可以有多个线程)

进程和线程的关系

  • 一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。
  • 资源分配给进程,同一进程的所有线程共享该进程的所有资源。
  • 处理机分给线程,即真正在处理机上运行的是线程。
  • 线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。线程是指进程内的一个执行单元,也是进程内的可调度实体。
  • 线程是在进程内部工作,而进程负责向外界输出。
  • 一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。
  • 不同进程之间也可以通信,不过代价较大

线程的优点

  • 易于调度。
  • 提高并发性。通过线程可方便有效地实现并发性。进程可创建多个线程来执行同一程序的不同部分。
  • 开销少。创建线程比创建进程要快,所需开销很少。
  • 利于充分发挥多处理器的功能。通过创建多线程进程,每个线程在一个处理器上运行,从而实现应用程序的并发性,使每个处理器都得到充分运行

浏览器中的进程

浏览器是一个多进程模型

  • 浏览器进程:负责界面显示、用户交互、子进程管理,提供存储等。
  • 渲染进程:每个 tab 页都有单独的渲染进程,核心用于渲染页面,取得网页的内容(HTML、XML、图像等等)、整理讯息(例如加入 CSS 等),以及计算网页的显示方式,然后会输出至显示器
  • 网络进程:主要处理网络资源加载(HTML、CSS,、JS 等)
  • GPU 进程:3d 绘制,提高性能
  • 插件进程: chrome 中安装的一些插件
进程&线程

什么是单线程

单线程就是一个进程中只有一个线程。程序顺序执行,前面的执行完,才会执行后面的程序。

JS 为什么是单线程的

现在有 2 个进程,process1 process2,由于是多进程的 JS,所以他们对同一个 dom,同时进行操作。process1 删除了该 dom,而 process2 编辑了该 dom, 这样会对浏览器同时下达两个矛盾的命令,这是不合理的

JS 为什么需要异步

如果 JS 中不存在异步,只能自上而下执行,如果上一行解析时间很长,那么下面的代码就会被阻塞。对于用户而言,阻塞就意味着"卡死",这样就导致了很差的用户体验

JS 单线程又是如何实现异步

console.log(1);
setTimeout(function () {
  console.log(2);
}, 0);
console.log(3);

上述代码会依次输出 1 3 2

由于 Js 的执行机制(只要主线程空了,就会去读取任务队列)导致的,js 中所有任务可以分成两种, 一种是同步任务(synchronous),另一种是异步任务(asynchronous)。

  • 同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;
  • 异步任务指的是,不进入主线程、而进入任务队列的任务,只有任务队列通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

event loop

  • 所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
  • 主线程之外,还存在一个任务队列(event queue)。只要异步任务有了运行结果,就在任务队列之中放置一个事件。
  • 一旦执行栈中的所有同步任务执行完毕,系统就会读取任务队列(event queue),看看里面有哪些异步任务可以执行,进入执行栈,开始执行。
  • 主线程不断重复上面的第三步。(event loop)

事件和回调函数

  • 任务队列是一个事件的队列(也可以理解成消息的队列),IO 设备完成一项任务,就在任务队列中添加一个事件,表示相关的异步任务可以进入执行栈了。主线程读取任务队列,就是读取里面有哪些事件。
  • 任务队列中的事件,除了 IO 设备的事件以外,还包括一些用户产生的事件(比如鼠标点击、页面滚动等等)。只要指定过回调函数,这些事件发生时就会进入任务队列,等待主线程读取。
  • 所谓回调函数(callback),就是那些会被主线程挂起来的代码。异步任务必须指定回调函数,当主线程开始执行异步任务,就是执行对应的回调函数。
  • 任务队列是一个先进先出的数据结构,排在前面的事件,优先被主线程读取。主线程的读取过程基本上是自动的,只要执行栈一清空,任务队列上第一位的事件就自动进入主线程。但是,由于存在后文提到的定时器功能,主线程首先要检查一下执行时间,某些事件只有到了规定的时间,才能返回主线程。

定时器执行的过程

定时器功能主要由 setTimeout() 和 setInterval() 这两个函数来完成。它们的内部运行机制完全一样,区别在于前者指 定的代码是一次性执行,后者则为反复执行。以下主要讨论 setTimeout()。

console.log(1);
setTimeout(function () {
  console.log(2);
}, 2000);
console.log(3);

上面代码的执行结果是 1,3,2,因为 setTimeout() 将第二行推迟到 2000 毫秒之后执行

如果将 setTimeout() 的第二个参数设为 0,就表示当前代码执行完(执行栈清空)以后,立即执行(0 毫秒间隔)指定的回调函数。 setTimeout(fn,0) 的含义是,指定某个任务在主线程最早可得的空闲时间执行,也就是说,尽可能早得执行。 它在”任务队列”的尾部添加一个事件,因此要等到同步任务和”任务队列”现有的事件都处理完,才会得到执行。

  • HTML5 标准规定了 setTimeout() 的第二个参数的最小值(最短间隔),不得低于 4 毫秒,如果低于这个值,就会自动增加。在此之前,老版本的浏览器都将最短间隔设为 10 毫秒。
  • 需要注意的是,setTimeout() 只是将事件插入了任务队列,必须等到当前代码(执行栈)执行完,主线程才会去执行它指定的回调函数。 要是当前代码耗时很长,有可能要等很久,所以并没有办法保证,回调函数一定会在 setTimeout() 指定的时间执行。

从哪里可以得出 javaScript 是单线程

比如你页面一上来就 alert(“hello world~”);只要你不关闭这个对话框,后续的 js 代码就不会再执行。 因为,单线程就是这样一步一步的顺次执行,前面不执行完,后面不会执行。也就是说,在具体的某一时刻,只有一段代码在执行。

多线程

多线程就是一个进程中只有多个线程。在进程内部进行线程间的切换,由于每个线程执行的时间片很短,所以在感觉上是并行的。

多线程优点

  • 使用线程可以把占据时间长的程序中的任务放到后台去处理
  • 用户界面可以更加吸引人,这样比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度
  • 程序的运行速度可能加快
  • 在一些等待的任务实现上如用户输入、文件读写和网络收发数据等,线程就比较有用了。在这种情况下可以释放一些珍贵的资源如内存占用等等。

多线程的缺点

如果有大量的线程,会影响性能,因为操作系统需要在它们之间切换。 更多的线程需要更多的内存空间。 线程可能会给程序带来更多“bug”,因此要小心使用。 线程的中止需要考虑其对程序运行的影响。 通常块模型数据是在多个线程间共享的,需要防止线程死锁情况的发生。 系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤消线程时的开销

💬留言板0

还没有留言,来发表第一条吧~

PAGE LOAD / LIVE进程与线程、浏览器多进程与 JS Event Loop加载中