1. 程式人生 > >瀏覽器核心中各個執行緒之間的關係

瀏覽器核心中各個執行緒之間的關係

 

到了這裡,已經對瀏覽器的執行有了一個整體的概念,接下來,先簡單梳理一些概念 :

 

GUI渲染執行緒與JS引擎執行緒互斥

 

由於JavaScript是可操縱DOM的,如果在修改這些元素屬性同時渲染介面(即JS執行緒和UI執行緒同時執行),那麼渲染執行緒前後獲得的元素資料就可能不一致了。

因此為了防止渲染出現不可預期的結果,瀏覽器設定GUI渲染執行緒與JS引擎為互斥的關係,當JS引擎執行時GUI執行緒會被掛起,
GUI更新則會被儲存在一個佇列中等到JS引擎執行緒空閒時立即被執行。

 

JS阻塞頁面載入

 

從上述的互斥關係,可以推匯出,JS如果執行時間過長就會阻塞頁面。

譬如,假設JS引擎正在進行巨量的計算,此時就算GUI有更新,也會被儲存到佇列中,等待JS引擎空閒後執行。
然後,由於巨量計算,所以JS引擎很可能很久很久後才能空閒,自然會感覺到巨卡無比。

所以,要儘量避免JS執行時間過長,這樣就會造成頁面的渲染不連貫,導致頁面渲染載入阻塞的感覺。

 

WebWorker,JS的多執行緒?

 

前文中有提到JS引擎是單執行緒的,而且JS執行時間過長會阻塞頁面,那麼JS就真的對cpu密集型計算無能為力麼?

所以,後來HTML5中支援了Web Worker

 

MDN的官方解釋是:

Web Worker為Web內容在後臺執行緒中執行指令碼提供了一種簡單的方法。執行緒可以執行任務而不干擾使用者介面  一個worker是使用一個建構函式建立的一個物件(e.g. Worker()) 執行一個命名的JavaScript檔案   這個檔案包含將在工作執行緒中執行的程式碼; workers 執行在另一個全域性上下文中,不同於當前的window  因此,使用 window快捷方式獲取當前全域性的範圍 (而不是self) 在一個 Worker 內將返回錯誤

 

這樣理解下:

  • 建立Worker時,JS引擎向瀏覽器申請開一個子執行緒(子執行緒是瀏覽器開的,完全受主執行緒控制,而且不能操作DOM)

  • JS引擎執行緒與worker執行緒間通過特定的方式通訊(postMessage API,需要通過序列化物件來與執行緒互動特定的資料)

 

所以,如果有非常耗時的工作,請單獨開一個Worker執行緒,這樣裡面不管如何翻天覆地都不會影響JS引擎主執行緒,
只待計算出結果後,將結果通訊給主執行緒即可,perfect!

而且注意下,JS引擎是單執行緒的,這一點的本質仍然未改變,Worker可以理解是瀏覽器給JS引擎開的外掛,專門用來解決那些大量計算問題。

其它,關於Worker的詳解就不是本文的範疇了,因此不再贅述。