眾所周知,JS 使用事件回圈在單執行緒上模擬多執行緒。我對它的效率感到困惑。
假設我們要讀取一個檔案,并且有一種方法可以使用 linuxread系統函式。據我所知,當read函式運行時,CPU 會將作業發送到 DMA,以便 CPU 可以做其他事情。
在其他真正的多執行緒語言(如 C )中,我們創建一個新執行緒來讀取檔案。在 DMA 處理檔案時,CPU 可以真正從該檔案讀取執行緒切換到執行一些其他作業。
但是在 JS 中,只有一個執行緒真正起作用。即使現在你把這個讀取檔案的作業放在一邊,但將來你必須在這個執行緒上做那個作業。每當你想呼叫read函式時,你必須已經在執行緒的堆疊中,即使 CPU 可以將作業留給 DMA,執行緒仍然阻塞在那里并且不能跳轉到其他執行緒(因為只有一個執行緒,對嗎?)
所以我認為JS的事件回圈模型并不是真正的并發,對吧?即使它可以暫時擱置作業,它仍然需要相同的時間來處理作業。總執行時間不會減少。我很困惑,請幫助我。
uj5u.com熱心網友回復:
即使 JavaScript 是單執行緒的(它不再是多虧了 Web Workers),你也可以要求作業系統同時執行許多 I/O 操作:
我們可以使用非阻塞 I/O,而不是使用阻塞 I/O,我們要求作業系統讓執行緒休眠,直到資料在這里,我們可以使用非阻塞 I/O,我們要求作業系統獲取資料,并在資料到達時通知我們,允許我們同時做其他事情。
例如,在 node.js 檔案系統 API 中,每個函式都以多種形式存在:
- 同步 API 同步執行所有操作,阻塞事件回圈,直到操作完成或失敗。
- 回呼 API 異步執行所有操作,不會阻塞事件回圈,然后在完成或錯誤時呼叫回呼函式(回呼 API 使用底層 Node.js 執行緒池在事件回圈執行緒之外執行檔案系統操作)。
- Promises API 與回呼 API 類似,但更易于使用。
所以我們可以選擇是想睡覺直到資料在這里,還是在那段時間做其他事情。
值得注意的是,實際的硬體是非阻塞的。例如,直接記憶體訪問允許磁盤在不涉及 CPU 的情況下將資料放入記憶體中,并在傳輸完成后中斷 CPU。
uj5u.com熱心網友回復:
您可以使用 web-workers 在 javascript 中運行真正的多執行緒。您無法在單執行緒環境中模擬多執行緒。異步和多執行緒不是一回事。您可以在 javascript 中運行異步,但不能在多執行緒中運行(沒有 WebWorkers)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/486656.html
標籤:javascript 多线程 并发
