JavaScript是單線程
為甚麼是單線程?
JavaScript的單線程,與它的用途有關。作為瀏覽器腳本語言,JavaScript的主要用途是與用戶互動,以及操作DOM。這決定了它只能是單線程,否則會帶來很複雜的同步問題。比如,假定JavaScript同時有兩個線程,一個線程在某個DOM節點上添加內容,另一個線程刪除了這個節點,這時瀏覽器應該以哪個線程為準?
所以,為了避免複雜性,從一誕生,JavaScript就是單線程,這已經成了這門語言的核心特徵,將來也不會改變。
為了利用多核CPU的計算能力,HTML5提出Web Worker標準,允許JavaScript腳本創建多個線程,但是子線程完全受主線程控制,且不得操作DOM。所以,這個新標準並沒有改變JavaScript單線程的本質。
單線程**(single threaded)的意義:在於JavaScript只能一次執行一段程式碼。在 JavaScript 中目前執行到程式的哪個部分會以堆疊(stack)**方式記錄,如果進入了某一個函式(step into),便把這個函式添加到堆疊(stack)當中的最上方;如果在函式中執行了 return ,則會將此函式從堆疊(stack)的最上方中離開推疊(pop off)。
stack順序如下:main() => $.getSync('foo.com')(移入) => $.getSync('foo.com')(移出) => $.getSync('bar.com')(移入) => $.getSync('bar.com')… => console.log(foo)(移入) => console.log(foo)(移出)…
所以也因為這樣一次只能執行一個執行序,所以會塞車,像上面動畫這樣。假設請求資料的 AJAX Request 變成(Synchronous)處理的話,那麼每請求一次,因為必需等這個函式執行完畢從堆疊(stack)中移出後才能往下繼續走,進而導致塞車的情形產生。
進程(Process) 與 線程(Thread)
什麼是進程(Process) ?
可以將工作管理員打開,這時後你會看到許多執行應用程式,每個應用程式或許命名為 ****.exe。是的,可以把每一個 ****.exe 都當作一個進程來看待。
什麼是線程(Thread)?
那 ****.exe 中可能會做很多事,像是瀏覽器,當你點擊它的時候,它幫你開網頁;當你不知不覺,它就幫你更新好了你有安裝的相關套件的最新版,可以把它們各自都當作是一個線程來看待。
線程(Thread)與進程(Process)的關係?
進程擁有自己的系統資源,而且互相不影響,所以如果一個進程 crash 掉並不會對其他的進程造成影響。線程則是由進程堆疊起來的,所以當線程 crash 掉了,所有的進程也會跟著 crash。也因此多進程的程序是比多線程的程序健康的,但是進程在切換時,耗費資源會較多,效率會比較差。
單線程和多線程
多線程語言則是能同時執行多個任務/程式碼塊,例如: C#, Java, C++ 這些語言都是多線程的。
最主要的差別在於:
- 多線程語言可以真正的在多個執行緒中同時執行多個任務,而 JavaScript 只能在單個執行緒中透過異步程式設計來模擬多個任務的同時執行。
- 多線程語言需要進行資源競爭的處理,而 JavaScript 由於是單線程,所以不存在資源競爭的問題。
JavaScript 透過異步程式設計可以在不阻塞主執行緒的情況下執行多個任務,並且不需要進行資源競爭的處理,進而提高程式效率和效能。