這篇文章是上一篇博客的補充,旨在把沒有講清楚的「用戶級執行緒和內核級執行緒」補充完整,希望讀者能對執行緒有更進一步的了解,
小白最近在學習多執行緒編程,
網上關于多執行緒的資料很多,小白很快就把執行緒的基本概念弄懂了,但關于「用戶級執行緒和內核級執行緒」的概念,她卻怎么也搞不清楚,只好向作業系統基礎扎實的小明請教,
對于小白的問題,小明總會耐心解答:“執行緒里面這兩個概念確實比較難理解,我先給你講用戶級執行緒吧,”
用戶級執行緒
“既然你說你已經看過執行緒的基本概念,那我就直接跳過這一部分了,
很久很久之前,執行緒的概念是出現了,但作業系統廠商可不能直接就去修改作業系統的內核,因為對他們來說,穩定性是最重要的,貿然把未經驗證的東西加入內核,出問題了怎么辦?所以想要驗證執行緒的可用性,得另想辦法,”
“我知道我知道,那些研究人員就撰寫了一個關于執行緒的函式庫,用函式庫來實作執行緒!”小白得意的說:“這個我剛剛在網上看到了,”
“是的,他們把創建執行緒、終止執行緒等功能放在了這個執行緒庫內,用戶就可以通過呼叫這些函式來實作所需要的功能,”小明找了張紙,寫上了幾個函式:pthread_creat ,pthread_exit ,pthread_join ,pthread_yield ,接著說:“這是幾個重要的函式,你應該能大概猜出這些函式的功能吧?”
“emmmm,讓我想想,pthread_creat 是創建一個新執行緒,pthread_exit 是結束執行緒,pthread_join 嘛,我猜是準備運行某一個執行緒,然后把它加進就緒佇列,最后一個函式我就不知道了,”
“不知道也沒關系,一會你就清楚了,”小明接著講:“要知道,剛剛我們說的執行緒庫,是位于用戶空間的,作業系統內核對這個庫一無所知,所以從內核的角度看,它還是按正常的方式管理,”
小白問道:“也就是說作業系統眼里還是只有行程嘍?那我用執行緒庫寫的一個多執行緒行程,只能一次在一個 CPU 核心上運行?”
小明點點頭,說:“你說的沒錯,這其實是用戶級執行緒的一個缺點,這些執行緒只能占用一個核,所以做不到并行加速,而且由于用戶執行緒的透明性,作業系統是不能主動切換執行緒的,換句話講,如果 A,B 是同一個行程的兩個執行緒的話, A 正在運行的時候,執行緒 B 想要運行的話,只能等待 A 主動放棄 CPU,也就是主動呼叫 pthread_yield 函式,”
tobe 注:對作業系統來說,用戶級執行緒具有不可見性,也稱透明性,
“停一下,讓我想一想,”小白飛速思考著小明的話,“是不是說,即使有執行緒庫,用戶級執行緒也做不到像行程那樣的輪轉調度?”
“非常正確!看來你對行程的概念很清楚嘛,不過呢,雖然不能做到輪轉調度,但用戶級執行緒也有他自己的好處——你可以為你的應用程式定制調度演算法,畢竟什么時候退出執行緒你自己說了算,剛剛說了,因為作業系統只能看到行程的存在,那如果某一個執行緒阻塞了,你覺得會發生什么?”
“在作業系統眼里,是行程阻塞了,那么整個行程就會進入阻塞態,在阻塞操作結束前,這個行程都無法得到 CPU 資源,那就相當于,所有的執行緒都被阻塞了,”小白得意的回答,
“沒錯,所以如果任由執行緒進行阻塞操作,行程的效率將受到很大的影響,所以在這個程序中,出現了一個替代方案——jacket,所謂 jacket,就是把一個產生阻塞的系統呼叫轉化成一個非阻塞的系統呼叫,”
小白驚訝地問:“這怎么做得到?該阻塞的呼叫,還能變得不阻塞?”
小明答道:“我來舉個例子吧,不是直接呼叫一個系統 I/O 例程,而是呼叫一個應用級別的 I/O jacket 例程,這個 jacket 例程中的代碼會檢查并且確定 I/O 設備是不是正忙,如果忙的話,就在用戶態下將該執行緒阻塞,然后把控制權交給另一個執行緒,隔一段時間后再次檢查 I/O 設備,就像你說的,最后還是會執行阻塞呼叫,但使用 jacket 可以縮短被阻塞的時間,不過有些情況下是可以不被阻塞的,取決于具體的實作,”
小明停頓了一會,說:“用戶級執行緒的概念大概就這么多,我們接下來講內核級執行緒吧,”
內核級執行緒
“有了用戶級執行緒的鋪墊,內核級執行緒就好講多了,現在我們知道,許多作業系統都已經支持內核級執行緒了,為了實作執行緒,內核里就需要有用來記錄系統里所有執行緒的執行緒表,當需要創建一個新執行緒的時候,就需要進行一個系統呼叫,然后由作業系統進行執行緒表的更新,當然了,傳統的行程表也還是有的,你想想看,如果作業系統「看得見」執行緒,有什么好處?“
小白自信的回答:“作業系統內核如果知道執行緒的存在,就可以像調度多個行程一樣,把這些執行緒放在好幾個 CPU 核心上,就能做到實際上的并行了,”
“還有一點你沒有說到,如果執行緒可見,那么假如執行緒 A 阻塞了,與他同屬一個行程的執行緒也不會被阻塞,這是內核級執行緒的絕對優勢,”
“那內核級執行緒就沒有什么缺點嗎?”
“缺點當然是有的,你想想看,讓作業系統進行執行緒調度,那意味著每次切換執行緒,就需要「陷入」內核態,而作業系統從用戶態到內核態的轉變是有開銷的,所以說內核級執行緒切換的代價要比用戶級執行緒大,還有很重要的一點——執行緒表是存放在作業系統固定的表格空間或者堆疊空間里,所以內核級執行緒的數量是有限的,擴展性比不上用戶級執行緒,”
"內核級執行緒就這么點東西,我最后給你留一張圖,你要是能看得懂,就說明你理解今天的概念了,"

小白得意地說:“我當然看得懂了,謝謝小明!”
希望你在看完我的文章之后有所識訓,
感謝你的閱讀,我們后會有期!
宣告:原創文章,未經授權,禁止轉載
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/69234.html
標籤:C
上一篇:一個多項式的描述
