線程的前因後果,你瞭解嗎?

進程最近有些煩惱,整日愁眉苦臉的,拜訪內存的時候也有點心不在焉。算法

內存是個明眼人,開門見山的問道:「進程啊,最近遇到啥問題了?我看你最近情緒有點低落,有啥問題你就直接說出來嘛,我讓你們夥兒來一塊兒幫你想一想辦法。」多線程

進程嘆了口氣,說道:「唉,最近不是說 CPU 單核頻率到瓶頸了嗎?人類就用多核芯來彌補單核處理器性能的不足,我們的 CPU 不也升級到四核了嘛。」函數

「是啊,這是好事啊,如今最多能並行處理 4 個進程,效率比之前高多了,這還很差嗎?」內存疑惑的問。性能

「好是好,可我每次上 CPU 運行的時候,都忍不住去想,要是單核頻率不增長,我總的運行的時間不仍是沒有什麼變化嗎?之後的應用程序愈來愈大,愈來愈吃 CPU 資源,好比那些大型遊戲進程,在短期內須要進行大量計算,靠單核撐不住怎麼辦。不談之後,就說說我本身,我也想可以早點運行完,早點休息啊。」操作系統

tobe 注:很明顯單進程的運行時間是變小了的,不過這裏主要強調的是進程佔用 CPU 的時間。線程

內存點點頭,贊同道:「這個問題我卻是沒想到,多核處理器對單個進程確實不大友好。那咱得想辦法讓你可以同時使用幾個核心。不過我一時間也想不到什麼好辦法,仍是和你們一塊兒討論下吧。」3d

在討論會上,內存向你們說明了進程如今遇到的問題。blog

「一個進程怎麼並行?」進程調度器第一個發出疑問:「我總不能把一個進程放在四個核上吧,這樣不只毫無心義,還阻礙了其餘進程的執行。」遊戲

操做系統見多識廣,說:「把進程一次放在幾個核上運行確定是不可能的,我在想,我們的目標,其實就是讓多個核心不衝突地幫助一個進程運行嘛。那咱們就得把進程「拆開」,而後放在幾個核上。」進程

操做系統一邊說,一邊畫了張圖:

進程拆分

「大家看,假如說 fun1 和 fun2 這兩個函數互不關聯,咱們就可讓兩個核同時執行他們,這不就作到並行了嗎?」

「你的意思是說把一個進程拆成好幾個進程?」

操做系統搖搖頭:「不是拆成多個進程,進程切換的代價太大了,再說了,這些拆出來的函數,他們是共用一個地址空間的,天生就可以數據共享,若是拆成進程,咱們還得再考慮進程之間的通訊問題,那多麻煩。不過爲了跟進程區分,就叫他們「線程(Thread)」吧」

進程一驚,要把本身拆成線程?那本身不就沒了?趕緊問道:「那我豈不是沒有存在的餘地了?」

進程調度器也慌了:「要是沒了進程,我是否是也要被退休了?」

操做系統趕緊解釋道:大家誤會了,我要拆開的,是進程的執行流,進程不是包含了資源全部權執行流嗎,資源全部權仍是由進程來把控,執行流就分給幾個線程,就像這樣:

執行流

tobe 注:在進程模型裏,進程擁有對內存、I/O 通道、I/O 設備和文件等資源的控制權,稱之爲「資源全部權」。「執行流」能夠看作進程在 CPU 上的執行過程(直觀一點就是高級語言裏的語句)。

進程恍然大悟:「也就是說我仍然是資源的掌控者,那些線程就至關於幫我幹活的小弟?」

「沒錯,並且從這種角度看,你自己仍是一個單線程進程。」

聽了這麼久,內存發問了:「建立進程的時候,我要保存進程 PCB ,那爲了建立線程,我是否是還得建立一個 TCB(Thread Control Block)?」

「固然了,線程切換須要的信息就得存在 TCB 裏面。不過你放心,TCB 要比 PCB 小得多,因此線程切換會比進程切換快不少。」

多線程進程模型

你們聽完,紛紛以爲「線程」這個模型完美的解決了當前的問題,說道:「要不咱們如今就在操做系統裏添上線程模型吧,早點解決進程的問題。」

可是操做系統面露難色,說:「線程模型只是咱們的一個假想,貿然加進來的話,可能會出問題,系統崩潰可就很差了,仍是要以穩定爲主。。。但這個模型仍是得試的,要不咱們先建立一個線程庫,靠一個用戶級別的應用程序——線程調度器來管理這些線程吧。」

進程不解的問:「但是這樣的話,我仍是被分配在一個單獨的核心上啊,即便是多線程,也只能在單核上運行。再說了,若是這些線程裏有一個被阻塞,在你看來,是整個進程阻塞了,那其餘線程,即便是就緒態,也得不到 CPU 資源。」

操做系統仔細想了下,說:「沒辦法,用戶級線程確實有這兩個缺點,但相比起讓內核來實現線程,用戶級線程也有他的好處——線程切換不須要我進行狀態轉換(從用戶態到內核態),開銷小,除此以外,線程庫能夠有多個調度算法,可以爲應用程序量身定作調度算法。」

tobe 注:有一種解決線程阻塞的方案叫 jacketing,他能夠把一個產生阻塞的系統調用轉化成一個非阻塞的系統調用,好比說,不直接調用系統級的 I/O 例程,而是讓線程調用應用級的 I/O jacket 例程,這個 jacket 例程會檢查 I/O 設備是否忙,若是忙的話,就不執行 I/O 操做,轉而調度其餘線程,避免了因等待 I/O 設備而形成的進程阻塞。


用戶級線程很快投入使用,Linux系統中的 pthread(POSIX thread)庫能夠說是大獲成功,操做系統作出了一項重大決定——支持內核級線程。

內核級線程解決了進程並行的問題,除此以外,因爲內核看獲得線程的存在,一個線程阻塞了,位於同一個進程中的其它線程仍然可以運行。

用戶級線程和內核級線程

並行的問題解決了,進程表示本身十分開心。


但願你在看完個人文章以後有所收穫。

感謝你的閱讀,咱們後會有期!

聲明:原創文章,未經受權,禁止轉載

相關文章
相關標籤/搜索