操作系統(tǒng)的線程詳解
前言
這將是一個系列,一個關(guān)于進程、線程和 協(xié)程的系列。
主要用于:回顧和復(fù)習以往所學(xué)的知識 以及 希望這點經(jīng)驗?zāi)軌驇椭趯W(xué)習編程的你。
最初的幾章會講到一些相關(guān)的計算機理論知識,可能相對枯燥。但這是基礎(chǔ),是理解后面程序必備的概念。如果有疑惑,可以加微信討論,咱們一起進步。
線程的定義
線程(thread)是操作系統(tǒng)能夠進行運算的最小單位。同一進程中的多條線程將共享該進程中的全部系統(tǒng)資源,如虛擬地址空間,文件描述符和信號處理等等。
線程的實現(xiàn)方式
根據(jù)管理線程所發(fā)生的位置,我們將線程分為以下三類:
- 內(nèi)核支持線程內(nèi)核線程駐留在內(nèi)核空間,它們是內(nèi)核對象。有了內(nèi)核線程,每個用戶線程被映射或綁定到一個內(nèi)核線程。用戶線程在其生命期內(nèi)都會綁定到該內(nèi)核線程。一旦用戶線程終止,兩個線程都將離開系統(tǒng)。這被稱作”一對一”線程映射。優(yōu)點是調(diào)度靈活,缺點是內(nèi)核線程在用戶態(tài)和內(nèi)核態(tài)之間進行上下文切換,資源開銷大。
- 用戶級線程內(nèi)核對線程包一無所知。從內(nèi)核角度考慮,就是按正常的方式管理,即單線程進程(存在運行時系統(tǒng))。也就是說,如果因為進程中一個線程發(fā)生阻塞(如IO資源引起的阻塞),那么其他線程也將得不到執(zhí)行。
- 組合方式線程(posix線程調(diào)度模型,又稱posix規(guī)范)posix線程調(diào)度是一個混合模型,很靈活,足以在標準的特定實現(xiàn)中支持用戶級和內(nèi)核級的線程。模型中包括兩級調(diào)度–線程及和內(nèi)核實體級。線程級與用戶級線程類似,內(nèi)核實體由內(nèi)核調(diào)度。由線程庫來決定它需要多少內(nèi)核實體,以及他們是如何映射的。
上下文切換
- 什么是上下文切換?當下計算機系統(tǒng)中,CPU運行的線程數(shù)量遠超過CPU的核數(shù),而用戶卻感覺這些程序在同時運行。這得益于分時系統(tǒng)的設(shè)計理念——人們將CPU的時間劃分為若干小段。每個線程只能在其中有限個小段上執(zhí)行。待時間一到,CPU就會將線程掛起,使其進入就緒狀態(tài),而CPU轉(zhuǎn)而執(zhí)行下一個線程,只不過這個切換的過程對于用戶來說太快,感知不到而已。而在這一個過程中,CPU需要將當前線程的工作環(huán)境保存起來(遷出工作區(qū)),然后將即將執(zhí)行的線程的數(shù)據(jù)載入工作區(qū),這一過程我們稱之為上下文切換。拓展,上面說的是典型的被動上下文切換,又稱之為飛自愿性上下文切換。除此之外,還有因當前進程資源不足發(fā)生的自愿性上下文切換,以及,中斷信號導(dǎo)致的中斷上下文切換。
- 上下文切換的成本我在控制臺查看一下自己系統(tǒng)中上下文切換的次數(shù)。(滿載狀態(tài)下)
- $ sar -w 1 10
- Linux 4.15.0-153-generic (ubuntu-bionic) 08/09/21 _x86_64_ (2 CPU)
- 15:26:02 proc/s cswch/s
- 15:26:03 0.00 65892.00
- 15:26:04 0.00 248868.00
- 15:26:05 0.00 368564.00
- 15:26:06 0.00 391488.00
- 15:26:07 0.00 349058.00
- 15:26:08 0.00 353089.00
- 15:26:09 0.00 381352.00
- 15:26:10 0.00 379659.00
- 15:26:11 0.00 374822.00
- 15:26:12 0.00 129233.00
- Average: 0.00 304202.50
- # proc/s 每秒創(chuàng)建的任務(wù)總數(shù)。
- # cswch/s 每秒上下文切換的總數(shù)
我這是2核CPU,據(jù)統(tǒng)計目前主流的CPU每次上下文切換要花掉2~5微秒。我們?nèi)≈形粩?shù)3微秒。我們來計算一下每秒單核CPU花在上下文切換中的時間:3*304202/2/1000=0.456s??梢钥闯?,頻繁的上下文切換對性能的影響是巨大的。
由于同一個進程中的多個線程是共享進程資源的,所以從這個角度我們又把上下文切換分成兩類:
- 進程切換:不同進程的線程之間切換。
- 線程切換:統(tǒng)一進程中不同線程之間的切換。

上圖綠色的部分代表需要切換的上下文,我們可以看出,線程切換的開銷遠小于進程切換。
今天線程的理論只是就講到這里,接下來我們將以Python為主要編程語言,帶大家進行 多線程實踐與性能分析,相對于干燥的理論知識,將會變得比較有趣。