聊聊瀏覽器的多進程和多線程的事

我們要理解瀏覽器進程和線程之間的關係,首先要了解什麼是進程?什麼是線程?

1、進程

進程(Process)是計算機中的程序關於某數據集合上的一次運行活動,是系統進行資源分配和調度的基本單位。

示例

打開谷歌瀏覽器,隨便打開幾個網頁,按下shift+esc鍵,界面將顯示目前瀏覽器啓動的幾個進程,還有相應的進程內存佔用空間、CPU核數、進程ID等等。
在這裏插入圖片描述
在瀏覽器中新打開一個tab頁,瀏覽器會開啓一個新的進程,但是,這並不意味着,瀏覽器上每一個tab頁就是一個進程,因爲
有的頁面是通過鏈接跳轉打開的,熟悉前端的朋友知道html裏的a標籤 <a href="" target="_blank">打開tab</> 可以新開一個tab頁,這新開的和原先的屬於同一進程。

瀏覽器進程(Browser進程)

 瀏覽器的主進程(負責協調、主控),只有一個。作用有
    負責瀏覽器界面顯示,與用戶交互。如前進,後退等
    負責各個頁面的管理,創建和銷燬其他進程
    將Renderer進程得到的內存中的Bitmap,繪製到用戶界面上
    網絡資源的管理,下載等

GPU進程:

最多一個,用於3D繪製等,可禁止掉。

瀏覽器渲染進程(Renderer進程,內部是多線程的)

每一個標籤頁的打開都會創建一個瀏覽器渲染進程(瀏覽器內核)。默認每個Tab頁面一個進程,互不影響。主要作用爲頁面渲染,腳本執行,事件處理等

2、線程

線程(英語:thread)是操作系統能夠進行運算調度的最小單位。它被包含在進程之中,是進程中的實際運作單位。
一條線程指的是進程中一個單一順序的控制流,一個進程中可以併發多個線程,每條線程並行執行不同的任務。

一個程序運行會啓動多個進程,而進程裏又包含了多個線程,多個線程爲進程服務。
下圖爲瀏覽器渲染進程中存在的各個線程
在這裏插入圖片描述
GUI渲染線程

負責渲染瀏覽器界面,解析HTML,CSS,構建DOM樹和RenderObject樹,佈局和繪製等。
當界面需要重繪(Repaint)或由於某種操作引發迴流(reflow)時,該線程就會執行
注意,GUI渲染線程與JS引擎線程是互斥的,當JS引擎執行時GUI線程會被掛起(相當於被凍結了),
GUI更新會被保存在一個隊列中等到JS引擎空閒時立即被執行。

JS引擎線程

也稱爲JS內核,負責處理Javascript腳本程序。(例如V8引擎)
JS引擎線程負責解析Javascript腳本,運行代碼。
JS引擎一直等待着任務隊列中任務的到來,然後加以處理,一個Tab頁(renderer進程)中無論什麼時候都只有一個JS線程在運行JS程序
同樣注意,GUI渲染線程與JS引擎線程是互斥的,所以如果JS執行的時間過長,這樣就會造成頁面的渲染不連貫,導致頁面渲染加載阻塞。

事件觸發線程

歸屬於瀏覽器而不是JS引擎,用來控制事件循環(可以理解,JS引擎自己都忙不過來,需要瀏覽器另開線程協助)
當JS引擎執行代碼塊如setTimeOut時(也可來自瀏覽器內核的其他線程,如鼠標點擊、AJAX異步請求等),會將對應任務添加到事件線程中
當對應的事件符合觸發條件被觸發時,該線程會把事件添加到待處理隊列的隊尾,等待JS引擎的處理
注意,由於JS的單線程關係,所以這些待處理隊列中的事件都得排隊等待JS引擎處理(當JS引擎空閒時纔會去執行)

定時觸發器線程

傳說中的setInterval與setTimeout所在線程
瀏覽器定時計數器並不是由JavaScript引擎計數的,(因爲JavaScript引擎是單線程的, 如果處於阻塞線程狀態就會影響記計時的準確)
因此通過單獨線程來計時並觸發定時(計時完畢後,添加到事件隊列中,等待JS引擎空閒後執行)
注意,W3C在HTML標準中規定,規定要求setTimeout中低於4ms的時間間隔算爲4ms。

異步http請求線程

在XMLHttpRequest在連接後是通過瀏覽器新開一個線程請求
將檢測到狀態變更時,如果設置有回調函數,異步線程就產生狀態變更事件,將這個回調再放入事件隊列中。再由JavaScript引擎執行。

瀏覽器內核中線程之間的關係

GUI渲染線程與JS引擎線程互斥

因爲JS引擎可以修改DOM樹,那麼如果JS引擎在執行修改了DOM結構的同時,
GUI線程也在渲染頁面,那麼這樣就會導致渲染線程獲取的DOM的元素信息可能與JS引擎操作DOM後的結果不一致。
爲了防止這種現象,GUI線程與JS線程需要設計爲互斥關係,當JS引擎執行的時候,GUI線程需要被凍結,
但是GUI的渲染會被保存在一個隊列當中,等待JS引擎空閒的時候執行渲染。由此也可以推出,
如果JS引擎正在進行CPU密集型計算,那麼JS引擎將會阻塞,長時間不空閒,導致渲染進程一直不能執行渲染,
頁面就會看起來卡頓卡頓的,渲染不連貫,所以,要儘量避免JS執行時間過長。

JS引擎線程與事件觸發線程、定時觸發器線程、異步HTTP請求線程

事件觸發線程、定時觸發器線程、異步HTTP請求線程三個線程有一個共同點,那就是使用回調函數的形式,
當滿足了特定的條件,這些回調函數會被執行。這些回調函數被瀏覽器內核理解成事件,在瀏覽器內核中擁有一個事件隊列,
這三個線程當滿足了內部特定的條件,會將這些回調函數添加到事件隊列中,等待JS引擎空閒執行。例如異步HTTP請求線程,
線程如果檢測到請求的狀態變更,如果設置有回調函數,回調函數會被添加事件隊列中,等待JS引擎空閒了執行。
但是,JS引擎對事件隊列(宏任務)與JS引擎內的任務(微任務)執行存在着先後循序,當每執行完一個事件隊列的時間,
JS引擎會檢測內部是否有未執行的任務,如果有,將會優先執行(微任務)。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章