自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

瀏覽器是如何調(diào)度進(jìn)程和線程的?

系統(tǒng) 瀏覽器
今天我們來(lái)聊一下瀏覽器(以Chrome為例)對(duì)線程和進(jìn)程的調(diào)度,這個(gè)問(wèn)題幾乎是我每次面試必問(wèn)的。

最近正值秋招,面試了很多前端同學(xué),感悟頗多,后面我也會(huì)在公眾號(hào)為大家分享下我作為面試官的一些心得,以及對(duì)于我經(jīng)常會(huì)問(wèn)的一些問(wèn)題的講解。

[[345577]]

今天我們來(lái)聊一下瀏覽器(以Chrome為例)對(duì)線程和進(jìn)程的調(diào)度,這個(gè)問(wèn)題幾乎是我每次面試必問(wèn)的。相信大家都看過(guò)很多面經(jīng)會(huì)講 JavaScript 的執(zhí)行機(jī)制,很多同學(xué)熱衷于去背這些面經(jīng),以至于連 JavaScript 是單線程的都不知道,就開(kāi)始回答宏任務(wù)、微任務(wù)了... 這種我真的特別無(wú)語(yǔ),是真的理解還是背出來(lái)的解題思路其實(shí)一看便知了。所以我建議大家無(wú)論是準(zhǔn)備面試還是平時(shí)積累知識(shí),一定不要太浮躁,要從根本上理解這個(gè)問(wèn)題,而不是去記這些解題思路。

線程和進(jìn)程

首先我們來(lái)回顧下線程和進(jìn)程的概念:

  • 進(jìn)程:CPU 進(jìn)行資源分配的基本單位
  • 線程:CPU 調(diào)度的最小單位

這是進(jìn)程和線程最官方也是最常見(jiàn)的兩個(gè)定義,但是這兩個(gè)概念太抽象了,很難以理解。通俗一點(diǎn)講:進(jìn)程可以描述為一個(gè)應(yīng)用程序的執(zhí)行程序,線程則是進(jìn)程內(nèi)部用來(lái)執(zhí)行某個(gè)部分的程序。

下面再引用一段知乎的高贊回答,我感覺(jué)非常有意思:

做個(gè)簡(jiǎn)單的比喻:進(jìn)程=火車,線程=車廂

  • 線程在進(jìn)程下行進(jìn)(單純的車廂無(wú)法運(yùn)行)
  • 一個(gè)進(jìn)程可以包含多個(gè)線程(一輛火車可以有多個(gè)車廂)
  • 不同進(jìn)程間數(shù)據(jù)很難共享(一輛火車上的乘客很難換到另外一輛火車,比如站點(diǎn)換乘)
  • 同一進(jìn)程下不同線程間數(shù)據(jù)很易共享(A車廂換到B車廂很容易)
  • 進(jìn)程要比線程消耗更多的計(jì)算機(jī)資源(采用多列火車相比多個(gè)車廂更耗資源)
  • 進(jìn)程間不會(huì)相互影響,一個(gè)線程掛掉將導(dǎo)致整個(gè)進(jìn)程掛掉(一列火車不會(huì)影響到另外一列火車,但是如果一列火車上中間的一節(jié)車廂著火了,將影響到所有車廂)
  • 進(jìn)程可以拓展到多機(jī),進(jìn)程最多適合多核(不同火車可以開(kāi)在多個(gè)軌道上,同一火車的車廂不能在行進(jìn)的不同的軌道上)
  • 進(jìn)程使用的內(nèi)存地址可以上鎖,即一個(gè)線程使用某些共享內(nèi)存時(shí),其他線程必須等它結(jié)束,才能使用這一塊內(nèi)存。(比如火車上的洗手間)-"互斥鎖"
  • 進(jìn)程使用的內(nèi)存地址可以限定使用量(比如火車上的餐廳,最多只允許多少人進(jìn)入,如果滿了需要在門口等,等有人出來(lái)了才能進(jìn)去)-“信號(hào)量”

應(yīng)用程序如何調(diào)度進(jìn)程和線程

當(dāng)一個(gè)應(yīng)用程序啟動(dòng)時(shí),一個(gè)進(jìn)程就被創(chuàng)建了。應(yīng)用程序可能會(huì)創(chuàng)建一些線程幫助它完成某些工作,但這不是必須的。操作系統(tǒng)會(huì)劃分出一部分內(nèi)存給這個(gè)進(jìn)程,當(dāng)前應(yīng)用程序的所有狀態(tài)都將保存在這個(gè)私有的內(nèi)存空間中。

當(dāng)你關(guān)閉應(yīng)用時(shí),進(jìn)程也就自動(dòng)蒸發(fā)掉了,操作系統(tǒng)會(huì)將先前被占用的內(nèi)存空間釋放掉。

一個(gè)程序并不一定只有一個(gè)進(jìn)程,進(jìn)程可以讓操作系統(tǒng)再另起一個(gè)進(jìn)程去處理不同的任務(wù)。當(dāng)這種情況發(fā)生時(shí),新的進(jìn)程又將占據(jù)一塊內(nèi)存空間。當(dāng)兩個(gè)進(jìn)程需要通信時(shí),它們進(jìn)行進(jìn)程間通訊。

許多應(yīng)用程序都被設(shè)計(jì)成以這種方式進(jìn)行工作,所以當(dāng)其中一個(gè)進(jìn)程掛掉時(shí),它可以在其他進(jìn)程仍然運(yùn)行的時(shí)候直接重啟。

多進(jìn)程和多線程

理解了上面的內(nèi)容,我們?cè)賮?lái)重新梳理多進(jìn)程和多線程的概念:

  • 多進(jìn)程:多進(jìn)程指的是在同一個(gè)時(shí)間里,同一個(gè)計(jì)算機(jī)系統(tǒng)中如果允許兩個(gè)或兩個(gè)以上的進(jìn)程處于運(yùn)行狀態(tài)。多進(jìn)程帶來(lái)的好處是明顯的,比如你可以聽(tīng)歌的同時(shí),打開(kāi)編輯器敲代碼,編輯器和聽(tīng)歌軟件的進(jìn)程之間絲毫不會(huì)相互干擾。
  • 多線程是指程序中包含多個(gè)執(zhí)行流,即在一個(gè)程序中可以同時(shí)運(yùn)行多個(gè)不同的線程來(lái)執(zhí)行不同的任務(wù),也就是說(shuō)允許單個(gè)程序創(chuàng)建多個(gè)并行執(zhí)行的線程來(lái)完成各自的任務(wù)。

Chrome 的多進(jìn)程架構(gòu)

由于瀏覽器本身沒(méi)有統(tǒng)一的規(guī)范,不同的瀏覽器之間的架構(gòu)可能完全不同,在瀏覽器剛被設(shè)計(jì)出來(lái)的時(shí)候,那時(shí)的網(wǎng)頁(yè)非常的簡(jiǎn)單,每個(gè)網(wǎng)頁(yè)的資源占有率是非常低的,因此一個(gè)進(jìn)程處理多個(gè)網(wǎng)頁(yè)時(shí)可行的。然后在今天,大量網(wǎng)頁(yè)變得日益復(fù)雜。把所有網(wǎng)頁(yè)都放進(jìn)一個(gè)進(jìn)程的瀏覽器面臨在健壯性,響應(yīng)速度,安全性方面的挑戰(zhàn),所以大部分現(xiàn)代瀏覽器都是多進(jìn)程的。

從上面的圖我們可以很明顯的看出 Chrome 是一個(gè)多進(jìn)程的架構(gòu),我們打開(kāi)一個(gè)瀏覽器時(shí)會(huì)啟動(dòng)多個(gè)不同的進(jìn)程協(xié)助瀏覽器將頁(yè)面為我們呈現(xiàn)出來(lái):

  • 瀏覽器進(jìn)程
  • 插件進(jìn)程
  • GPU進(jìn)程
  • 渲染進(jìn)程

(1) 瀏覽器進(jìn)程

瀏覽器最核心的進(jìn)程,負(fù)責(zé)管理各個(gè)標(biāo)簽頁(yè)的創(chuàng)建和銷毀、頁(yè)面顯示和功能(前進(jìn),后退,收藏等)、網(wǎng)絡(luò)資源的管理,下載等。

(2) 插件進(jìn)程

負(fù)責(zé)每個(gè)第三方插件的使用,每個(gè)第三方插件使用時(shí)候都會(huì)創(chuàng)建一個(gè)對(duì)應(yīng)的進(jìn)程、這可以避免第三方插件crash影響整個(gè)瀏覽器、也方便使用沙盒模型隔離插件進(jìn)程,提高瀏覽器穩(wěn)定性。

(3) GPU進(jìn)程

負(fù)責(zé)3D繪制和硬件加速

(4) 渲染進(jìn)程

瀏覽器會(huì)為每個(gè)窗口分配一個(gè)渲染進(jìn)程、也就是我們常說(shuō)的瀏覽器內(nèi)核,這可以避免單個(gè) page crash 影響整個(gè)瀏覽器。

瀏覽器內(nèi)核的多線程

瀏覽器內(nèi)核就是瀏覽器渲染進(jìn)程,從接收下載文件后再到呈現(xiàn)整個(gè)頁(yè)面的過(guò)程,由瀏覽器渲染進(jìn)程負(fù)責(zé)。瀏覽器內(nèi)核是多線程的,在內(nèi)核控制下各線程相互配合以保持同步,一個(gè)瀏覽器通常由以下常駐線程組成:

  • GUI 渲染線程
  • 定時(shí)觸發(fā)器線程
  • 事件觸發(fā)線程
  • 異步http請(qǐng)求線程
  • JavaScript 引擎線程

(1) GUI渲染線程

GUI 渲染線程負(fù)責(zé)渲染瀏覽器界面 HTML 元素,當(dāng)界面需要重繪(Repaint)或由于某種操作引發(fā)回流(reflow)時(shí),該線程就會(huì)執(zhí)行。

(2) 定時(shí)觸發(fā)器線程

瀏覽器定時(shí)計(jì)數(shù)器并不是由 JavaScript 引擎計(jì)數(shù)的, 因?yàn)?JavaScript 引擎是單線程的, 如果處于阻塞線程狀態(tài)就會(huì)影響記計(jì)時(shí)的準(zhǔn)確, 因此通過(guò)單獨(dú)線程來(lái)計(jì)時(shí)并觸發(fā)定時(shí)是更為合理的方案。

(3) 事件觸發(fā)線程

當(dāng)一個(gè)事件被觸發(fā)時(shí)該線程會(huì)把事件添加到待處理隊(duì)列的隊(duì)尾,等待JS引擎的處理。這些事件可以是當(dāng)前執(zhí)行的代碼塊如定時(shí)任務(wù)、也可來(lái)自瀏覽器內(nèi)核的其他線程如鼠標(biāo)點(diǎn)擊、AJAX異步請(qǐng)求等,但由于JS的單線程關(guān)系所有這些事件都得排隊(duì)等待JS引擎處理。

(4) 異步http請(qǐng)求線程

在XMLHttpRequest在連接后是通過(guò)瀏覽器新開(kāi)一個(gè)線程請(qǐng)求, 將檢測(cè)到狀態(tài)變更時(shí),如果設(shè)置有回調(diào)函數(shù),異步線程就產(chǎn)生狀態(tài)變更事件放到 JavaScript引擎的處理隊(duì)列中等待處理。

(5) Javascript引擎線程

Javascript 引擎,也可以稱為JS內(nèi)核,主要負(fù)責(zé)處理 Javascript 腳本程序,例如V8引擎。Javascript 引擎線程理所當(dāng)然是負(fù)責(zé)解析 Javascript 腳本,運(yùn)行代碼。

由于 JavaScript 是可操縱 DOM 的,如果在修改這些元素屬性同時(shí)渲染界面(即 JavaScript 線程和UI線程同時(shí)運(yùn)行),那么渲染線程前后獲得的元素?cái)?shù)據(jù)就可能不一致了。因此為了防止渲染出現(xiàn)不可預(yù)期的結(jié)果,瀏覽器設(shè)置 GUI 渲染線程與 JavaScript 引擎為互斥的關(guān)系,當(dāng) JavaScript 引擎執(zhí)行時(shí) GUI 線程會(huì)被掛起, GUI 更新會(huì)被保存在一個(gè)隊(duì)列中等到引擎線程空閑時(shí)立即被執(zhí)行。

JavaScript 為何設(shè)計(jì)成單線程

從上面我們了解到 JavaScript 的執(zhí)行是單線程的,也就是說(shuō),同一個(gè)時(shí)間只能做一件事。那么,為什么 JavaScript 不設(shè)計(jì)成多個(gè)線程呢?這樣不是效率更高?

作為瀏覽器腳本語(yǔ)言, JavaScript 的主要用途是與用戶互動(dòng),以及操作DOM。這決定了它只能是單線程,否則會(huì)帶來(lái)很復(fù)雜的同步問(wèn)題。比如,假定 JavaScript 同時(shí)有兩個(gè)線程,一個(gè)線程在某個(gè) DOM 節(jié)點(diǎn)上添加內(nèi)容,另一個(gè)線程刪除了這個(gè)節(jié)點(diǎn),這時(shí)瀏覽器應(yīng)該以哪個(gè)線程為準(zhǔn)?

所以,為了避免復(fù)雜性,從一誕生, JavaScript 就是單線程,這已經(jīng)成了這門語(yǔ)言的核心特征,將來(lái)也不會(huì)改變。

WebWorker 多線程?

Web Worker為Web內(nèi)容在后臺(tái)線程中運(yùn)行腳本提供了一種簡(jiǎn)單的方法。線程可以執(zhí)行任務(wù)而不干擾用戶界面:

那么既然 JavaScript 本身被設(shè)計(jì)為單線程,為何還會(huì)有像 WebWorker 這樣的多線程 API 呢?我們來(lái)看一下 WebWorker 的核心特點(diǎn)就明白了:

  • 創(chuàng)建 Worker 時(shí), JS 引擎向?yàn)g覽器申請(qǐng)開(kāi)一個(gè)子線程(子線程是瀏覽器開(kāi)的,完全受主線程控制,而且不能操作DOM)
  • JS 引擎線程與 worker 線程間通過(guò)特定的方式通信(postMessage API,需要通過(guò)序列化對(duì)象來(lái)與線程交互特定的數(shù)據(jù))

所以 WebWorker 并不違背 JS引擎是單線程的 這一初衷,其主要用途是用來(lái)減輕cpu密集型計(jì)算類邏輯的負(fù)擔(dān)。

最后

好了,了解完以上知識(shí),再去學(xué)習(xí) JavaScript 的執(zhí)行機(jī)制吧,這些知識(shí)會(huì)讓你更快深入的理解。

 

責(zé)任編輯:趙寧寧 來(lái)源: code秘密花園
相關(guān)推薦

2013-07-25 14:17:17

2021-06-29 10:21:10

Mozilla Firefox 瀏覽器 web安全

2009-03-23 08:52:51

2019-12-02 13:46:35

瀏覽器前端開(kāi)發(fā)

2022-02-10 09:30:00

VRARWeb應(yīng)用程序

2011-06-21 10:06:48

2010-04-05 21:57:14

Netscape瀏覽器

2018-08-30 08:47:59

瀏覽器web服務(wù)器通信

2021-02-26 14:40:16

Kubernetes調(diào)度器

2019-03-05 10:48:24

Web瀏覽器前端

2016-01-22 12:17:34

代碼瀏覽器爆炸

2018-12-17 11:40:39

2016-05-18 14:13:02

Edge瀏覽器微軟

2010-11-03 15:39:19

2023-10-26 08:59:42

2016-06-02 13:22:12

LinuxWeb瀏覽器

2016-01-21 10:55:04

2012-03-19 17:25:22

2012-03-20 11:41:18

海豚瀏覽器

2012-03-20 11:31:58

移動(dòng)瀏覽器
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)