天天看點

linux+線程的前世今生,線程的前世今生

線程的前世今生

程序

早期的計算機隻有一個單核 CPU, 作業系統把程序作為 CPU 排程單元. 程序擁有獨立的記憶體位址空間, 那時候還沒有線程的概念.

程序有 3 個狀态, 分别是阻塞, 就緒, 運作. 當程序所需資源未到位時是阻塞狀态, 當程序擁有資源但未被 CPU 排程是就緒狀态, 當程序用有資源并且被 CPU 排程了就是運作狀态.

使用者态線程

随着程式越來越複雜, 排程産生的上下文切換也越發昂貴, 于是程式員尋思能不能在同一位址空間 (Address Space) 下, 執行多個程序. 但作業系統核心出于保護目的, 禁止一個程序直接通路另一個程序的位址空間.

既然作業系統不支援, 程式員決定在使用者空間下維護一張線程表, 實作可以自行排程的 "程序", 這就是使用者态線程, 現在一般叫做纖程或協程.

使用者态線程的優勢有:

在使用者空間下進行線程切換的速度遠快于在作業系統核心中的實作

程式員可以自行實作垃圾回收器來回收線程

當線程數量過多時, 由于在使用者空間維護線程表, 不會占用大量的作業系統空間

使用者态線程的劣勢有:

由于作業系統不知道線程的存在, 是以當一個程序中的某一個線程進行系統調用時, 比如缺頁中斷而導緻線程阻塞, 此時作業系統會阻塞整個程序, 即使這個程序中其它線程還在工作

假如程序中一個線程長時間不釋放 CPU, 因為使用者空間并沒有時鐘中斷機制, 會導緻此程序中的其它線程得不到 CPU 而持續等待

核心态線程

伴随多核 CPU 的出現, 作業系統也開始支援線程了. 核心空間維護了一張線程表, 線程由核心排程, 這就是核心态線程, 也稱作輕量程序(Light Weight Process,LWP). 今天說的線程, 如非指定, 都是核心線程.

核心态線程的優勢有:

當一個線程阻塞時, 作業系統可以選擇将 CPU 交給同一程序中的其它線程, 或是其它程序中的線程, 而對于使用者态線程的排程隻能在本程序中執行, 直到作業系統剝奪了目前程序的 CPU

核心态線程的劣勢有:

所有可能阻塞線程的調用都是 System Call, 相比在使用者空間下造成線程阻塞的 System runtime call, 成本高出不少

建立和銷毀的成本更高. 為了降低成本, 當一個線程需要銷毀時, 僅作标記銷毀; 當需要建立一個線程時, 就複用被标記銷毀的線程即可

接收系統信号的機關是程序, 而不是線程, 那麼由程序中的哪一個線程接收系統信号呢

邏輯核心

"單核 CPU 在同一時間内隻能夠運作一個程序", 在過去很長一段時間是對的, 直至同時多線程 (SMT) 的出現. 超标量處理器 (1 個 CPU 實體核心) 可以同時跑超過一個線程, 例如 Intel 的 hyperthreading 支援一個實體核心跑兩個線程. 講幾核的 CPU 的核心數一般指實體核心數, 如果是指邏輯核心數一般直接會說線程數, 幾個邏輯核心就同時支援幾套架構狀态和幾個線程.

"單程序多線程可以同時用到 CPU 的雙核心", 在主流作業系統上沒問題. 對作業系統核心而言, 直接可見的 CPU 資源是邏輯核心, 可以排程的任務一般直接實作成 CPU 支援的線程, 是以 單核 CPU 可以同時跑多個任務.

不同作業系統中任務的概念不一樣:

Windows 排程的是線程, 程序隻是線程的容器

Linux 核心 不區分程序或者線程, 排程的任務在使用者空間可以被實作成一個程序或程序中的線程.

參考

作業系統中的程序與線程

多線程可以同時使用 CPU 的多個核心? https://www.v2ex.com/t/285551

來源: http://www.bubuko.com/infodetail-3424399.html