注意:本篇文章不是系統的線程知識講解,更多的是一些實用的線程常識和個人的筆記總結。如果讀者想要獲取更系統的OS線程知識講解,那麼本篇文章並不能很好的對你帶來幫助,請移步至更詳細系統的OS線程相關教程。
一、簡介
線程,有時又被稱爲輕量級進程,是程序執行流的最小單元。一個標準的線程由線程ID、當前指令指針(PC)、寄存器集合和堆棧組成。通常意義上,一個進程由一個到多個線程組成,各個線程之間共享程序的內存空間(包括代碼段、數據段、堆等)及一些進程級的資源(如打開文件和信號)。一個經典的線程與進程的關係如下:
二、訪問權限
線程的私有存儲空間包括以下幾個方面:
- 棧
- 線程局部存儲(TLS)。TLS是某些OS爲線程單獨提供的私有空間,通常容量很有限。
- 寄存器(包括PC寄存器)
對於C/C++程序員,可以參照以下表格:
線程私有 | 線程間共享 |
---|---|
局部變量 | 全局變量 |
函數的參數 | 堆上數據 |
TLS數據 | 函數中的靜態變量 |
程序代碼 | |
文件描述符 |
三、線程調度
不論是在多處理器的計算機上還是在單處理器的計算機上,線程總是“併發”執行的。當線程數量小於等於處理器數量時(並且OS支持多處理器),線程的併發是真正的併發,即不同的線程運行在不同的處理器上,彼此之間互不相干。但對於線程數量大於處理器數量的情況,線程的併發就不是真正的併發,因爲此時至少會有一個處理器運行多個線程,爲了更清楚的描述這種情況,下面用單處理器-多線程來說明:
在單處理器對應多線程的情況下,這種併發,是一種模擬出來的狀態。具體是這樣的:OS會讓這些多線程程序輪流執行,每次僅執行一小段時間(eg:幾十到幾百毫秒),這樣每個線程看起來就像是在“同時”執行。
這樣的一個不斷在處理器上切換不同的線程的行爲勢必會造成一些資源的浪費(線程切換浪費的時間),所以對應高性能服務器開發的一個建議就是:限制活躍線程數少於或等於CPU個數。
這裏對應的知識點參考:提升服務器性能的建議:減少環境切換帶來的開銷
一般情況下,通常把很少陷入等待狀態的線程稱爲 CPU密集型線程,而把頻繁陷入等待狀態的線程稱爲 IO密集型線程。 IO密集型線程總是比CPU密集型線程更容易得到優先級的提升。(進程也類似)
四、線程安全
//TODO
五、優點
- 某個操作可能會陷入長時間等待,等待的線程會進入睡眠狀態,無法繼續執行。多線程執行可以有效利用等待的時間。eg:等待網絡響應。
- 某個操作會消耗大量的時間(eg:計算),如果只有一個線程,程序和用戶的交互就會中斷。多線程就可以讓一個線程負責交互,一個線程負責計算。
- 程序邏輯本身就要求併發操作。eg:多端下載、監聽不同事件……
- 多CPU或者多core計算機,本身具備同時執行多個線程的能力,因此單線程程序無法全面的發揮計算機的全部性能。
- 多線程在數據共享方面相比多進程有天然的優勢。
六、缺點
- 健壯性不足。eg:一個線程出現異常退出,會導致整個進程退出。
- 多線程編程的難度比較高,需要開發人員更嚴謹。eg:如果進程的其中一個線程出現 Segmentation falut 而進程中又沒有SIGSEGV 信號的對應handler函數,那麼默認的動作就會導致整個進程退出。
七、實例
1. 生產者消費者模型
//TODO
2. 線程池
//TODO