三分鐘基礎:用戶級線程和內核級線程有什麼區別?

2021-03-02 帥地玩編程

來源:tobe的囈語

作者:tobe

小白最近在學習多線程編程。

網上關於多線程的資料很多,小白很快就把線程的基本概念弄懂了,但關於「用戶級線程和內核級線程」的概念,她卻怎麼也搞不清楚,只好向作業系統基礎紮實的小明請教。

ps:聽說小白看的是這篇文章——三分鐘基礎知識:線程的來龍去脈,你了解嗎?

對於小白的問題,小明總會耐心解答:「線程裡面這兩個概念確實比較難理解,我先給你講用戶級線程吧。」

用戶級線程

「既然你已經看過線程的基本概念,那我就直接跳過這一部分了。很久很久之前,線程的概念是出現了,但作業系統廠商可不能直接就去修改作業系統的內核,因為對他們來說,穩定性是最重要的。貿然把未經驗證的東西加入內核,出問題了怎麼辦?所以想要驗證線程的可用性,得另想辦法。」

「我知道我知道,那些研究人員就編寫了一個關於線程的函數庫,用函數庫來實現線程!」小白得意的說:「這個我剛剛在網上看到了。」

「是的,他們把創建線程終止線程等功能放在了這個線程庫內,用戶就可以通過調用這些函數來實現所需要的功能。」小明找了張紙,寫上了幾個函數:pthread_creat ,pthread_exit ,pthread_join ,pthread_yield ,接著說:「這是幾個重要的功能,我馬上會講到,你應該能大概猜出這些函數的功能吧?」

「emmmm,讓我想想,pthread_creat 是創建一個新線程,pthread_exit 是結束線程,pthread_join  嘛,我猜是準備運行,最後一個,我就不知道了。」

「不知道也沒關係,一會你就清楚了。」小明接著講:「要知道,剛剛我們說的線程庫,是位於用戶空間的,作業系統內核對這個庫一無所知,所以從內核的角度看,它還是按正常的方式管理。」

小白問道:「也就是說作業系統眼裡還是只有進程嘍?那我用線程庫寫的多線程進程,只能一次在一個 CPU 核心上運行?」

小明點點頭,說:「你說的沒錯,這其實是用戶級線程的一個缺點,這些線程只能佔用一個核,所以做不到並行加速,而且由於用戶線程的透明性,作業系統是不能主動切換線程的,換句話講,如果線程 A 正在運行,線程 B 想要運行的話,只能等待 A 主動放棄 CPU,也就是主動調用 pthread_yield 函數。」

tobe 註:對作業系統來說,用戶級線程具有不可見性,也稱透明性

「停一下,讓我想一想,」小白飛速思考著小明的話,「是不是說,即使有線程庫,用戶級線程也做不到像進程那樣的輪轉調度?」

「非常正確!看來你對進程的概念很清楚嘛。不過呢,雖然不能做到輪轉調度,但用戶級線程也有他自己的好處——你可以為你的應用程式定製調度算法,畢竟什麼時候退出線程你自己說了算。剛剛說了,因為作業系統只能看到進程的存在,那如果某一個線程阻塞了,你覺得會發生什麼?」

「在作業系統眼裡,是進程阻塞了,那麼整個進程就會進入阻塞態,在阻塞操作結束前,這個進程都無法得到 CPU 資源。那就相當於,所有的線程都被阻塞了。」小白得意的回答。

「沒錯,所以如果任由線程進行阻塞操作,進程的效率將受到很大的影響,所以在這個過程中,出現了一個替代方案——jacket。所謂 jacket,就是把一個產生阻塞的系統調用轉化成一個非阻塞的系統調用。」

小白驚訝地問:「這怎麼做得到?該阻塞的調用,還能變得不阻塞?」

小明答道:「我來舉個例子吧,不是直接調用一個系統 I/O 例程,而是調用一個應用級別的 I/O jacket 例程,這個 jacket 例程中的代碼會檢查並且確定 I/O 設備是不是正忙,如果忙的話,就在用戶態下將該線程阻塞,然後把控制權交給另一個線程。隔一段時間後再次檢查 I/O 設備。就像你說的,最後還是會執行阻塞調用,但使用 jacket 可以縮短被阻塞的時間。不過有些情況下是可以不被阻塞的,取決於具體的實現。」

小明停頓了一會,說:「用戶級線程的概念大概就這麼多,我們接下來講內核級線程吧。」

內核級線程

「有了用戶級線程的鋪墊,內核級線程就好講多了。現在我們知道,許多作業系統都已經支持內核級線程了。為了實現線程,內核裡就需要有用來記錄系統裡所有線程的線程表。當需要創建一個新線程的時候,就需要進行一個系統調用,然後由作業系統進行線程表的更新。當然了,傳統的進程表也還是有的。你想想看,如果作業系統「看得見」線程,有什麼好處?「

小白自信的回答:「作業系統內核如果知道線程的存在,就可以像調度多個進程一樣,把這些線程放在好幾個 CPU 核心上,就能做到實際上的並行了。」

「還有一點你沒有說到,如果線程可見,那麼假如線程 A 阻塞了,與他同屬一個進程的線程也不會被阻塞。這是內核級線程的絕對優勢。」

「那內核級線程就沒有什麼缺點嗎?」

「缺點當然是有的,你想想看,讓作業系統進行線程調度,那意味著每次切換線程,就需要「陷入」內核態,而作業系統從用戶態到內核態的轉變是有開銷的,所以說內核級線程切換的代價要比用戶級線程大。還有很重要的一點——線程表是存放在作業系統固定的表格空間或者堆棧空間裡,所以內核級線程的數量是有限的,擴展性比不上用戶級線程。」

"內核級線程就這麼點東西,我最後給你留一張圖,你要是能看得懂,就說明你理解今天的概念了。"

「我肯定能看懂!」

推薦閱讀

三分鐘基礎知識:線程的來龍去脈,你了解嗎?

三分鐘基礎知識:互斥那點事兒(下)

三分鐘基礎知識:互斥那點事兒(上)

關於進程與線程的一個簡單解釋

相關焦點

  • 線程和進程的關係與區別
    線程和進程的關係與區別 stranger huang 發表於 2020-11-29 11:01:23 可能學習嵌入式開發的讀者都聽說過這些專業名詞,但又多少人理解了
  • 進程和線程之間有什麼區別?看這!
    為此,就先要了解一下進程和線程的關係。線程在進程下行進,車廂只有在火車頭存在的情況下才能運行,單純的車廂無法運行,就像線程無法單獨運行。一個進程可以包括多個線程。一列火車可以拖拽多個車廂。相對的,同一進程下的不同線程之間的數據較易共享,就像在同一列車下的乘客可以在不同車廂中走動。因為線程是包括於進程之中,所以調用進程消耗的計算機資源要比調用線程所消耗的資源多得多。
  • pthread中線程是怎麼創建的(2)—glibc到內核
  • 進程、線程基礎知識全家桶,30 張圖一套帶走
    進程和線程對於寫代碼的我們,真的天天見、日日見了,但見的多不代表你就熟悉它們,比如簡單問你一句,你知道它們的工作原理和區別嗎?不知道沒關係,今天就要跟大家討論作業系統的進程和線程。並發和並行有什麼區別?一圖勝千言。
  • Linux筆記(19)| 線程基礎(三)
    前面兩節講了線程的一些基礎知識,這一節還是關於線程的內容,主要說一下線程的同步問題。
  • C++並發與多線程__C++如何線程創建線程以及函數join()和detach()用法和區別
    前言:通常一個程序運行起來,也就等於一個進程在運行,這個進程中會有一個主線程自動創建並運行,當程序的main()函數返回之後那麼此主線程也就運行結束
  • Linux 多線程詳解 —— 什麼是線程
    什麼是線程?linux內核中是沒有線程這個概念的,而是輕量級進程的概念:LWP。一般我們所說的線程概念是C庫當中的概念。
  • 並發的本質:線程和進程?
    本篇收錄於《offer快到碗裡來》寫在之前 "進程和線程有何區別?" 這個問題是校招面試中最最常見的問題了。很多人討厭這種背誦課本概念的問題,還請看管打住,稍後再噴;該問題還真是一個值得思考的問題。我們常常掛在嘴邊的,你有沒有經歷過什麼高並發項目,有沒有比較難以解決的高並發問題。面試時,如果說沒有遇到高並發問題似乎低人一等。
  • Java線程篇-線程的狀態和分類概述
    Java開發中線程是經常用到的技術,那麼讓我們來回顧一下一些線程中經常考慮的問題吧1、線程分為用戶線程和守護線程,有什麼區別2、線程有哪些運行狀態一、什麼是線程線程,>三、線程的分類線程可以分為守護線程和用戶線程兩種,那麼什麼是用戶線程,什麼是守護線程呢?
  • 5個步驟,教你瞬間明白線程和線程安全
    作者 | 一個程式設計師的成長責編 | 胡巍巍記得今年3月份剛來杭州面試的時候,有一家公司的技術總監問了我這樣一個問題:你來說說有哪些線程安全的類?我心裡一想,這我早都背好了,稀裡譁啦說了一大堆。他又接著問:那你再來說說什麼是線程安全?
  • 線程、進程、多線程、多進程和多任務有啥關係?
    一個線程可以創建和撤銷另一個線程,同一進程中的多個線程之間可以並發執行。由於線程之間的相互制約,致使線程在運行中呈現處間斷性。線程也有就緒、阻塞和運行三種基本狀態。就緒狀態是指線程具備運行的所有條件,邏輯上可以運行,在等待處理機;運行狀態是指線程佔有處理機正在運行;阻塞狀態是指線程在等待一個事件(如某個信號量),邏輯上不可執行。每一個程序都至少有一個線程,若程序只有一個線程,那就是程序本身。
  • 大數據基礎:Java多線程入門
    在大數據開發學習當中,Java基礎是非常重要的一部分,打好了Java基礎,才能在後續的大數據框架技術學習階段,也能有所主力。而Java當中的一個重要知識點,就是多線程。今天的大數據基礎分享,我們就主要來講講Java多線程入門基礎。
  • Java多線程編程必備基礎知識
    前言什麼是線程?線程,有時被稱為輕量進程(Lightweight Process,LWP),是程序執行流的最小單元。一個標準的線程由線程 ID,當前指令指針 (PC),寄存器集合和堆棧組成。另外,線程是進程中的一個實體,是被系統獨立調度和分派的基本單位,線程自己不擁有系統資源,只擁有一點兒在運行中必不可少的資源,但它可與同屬一個進程的其它線程共享進程所擁有的全部資源。一個線程可以創建和撤銷另一個線程,同一進程中的多個線程之間可以並發執行。由於線程之間的相互制約,致使線程在運行中呈現出間斷性。線程也有就緒、阻塞和運行三種基本狀態。
  • 新手編程:Java多線程中Thread與Runnable的區別
    Java多線程中Thread與Runnable的區別定義extends Thread子類繼承Thread具備多線程能力,可以實現多線程;啟動線程的方法:①創建子類對象 ②對象名.start();不建議使用:避免多線程OOP單繼承的局限性(OOP:Object Oriented Programming,面向對象的編程、類似的還有OOD
  • 【堪稱經典】JAVA多線程和並發基礎面試問答
    進程和線程之間有什麼不同?一個進程是一個獨立(self contained)的運行環境,它可以被看作一個程序或者一個應用。而線程是在進程中執行的一個任務。Java運行環境是一個包含了不同的類和程序的單一進程。線程可以被稱為輕量級進程。線程需要較少的資源來創建和駐留在進程中,並且可以共享進程中的資源。2. 多線程編程的好處是什麼?
  • 進程和線程常見的19個問題
    程序是產生進程的基礎程序的每次運行產生不同的進程進程是程序功能的體現通過多次執行,一個程序可對應多個進程;通過調用關係,一個進程可包括多個程序03進程和程序有什麼區別?進程是動態的,程序是靜態的:程序是有序代碼的集合,進程是程序的執行。
  • Java基礎知識點面試手冊(線程+JDK8)
    高並發編程多線程和單線程的區別和聯繫:答:在單核 CPU 中,將 CPU 分為很小的時間片,在每一時刻只能有一個線程在執行,是一種微觀上輪流佔用 CPU 的機制。多線程會存在線程上下文切換,會導致程序執行速度變慢,即採用一個擁有兩個線程的進程執行所需要的時間比一個線程的進程執行兩次所需要的時間要多一些。
  • 阿里面試官問我Java線程和作業系統線程什麼關係
    面試官:Java線程用過的吧?我:用過。面試官:那你給我講講Java線程和作業系統的?我:啊!!!咆哮劇情不應該這樣的啊,開場不應該先是 synchronized 或者 volatile,再然後是線程池和AQS,怎麼上來就整這玩意。我:好的,那我分三段講,1.
  • Java中的線程(狀態轉換和線程間通信)
    Java中的線程(狀態轉換和線程間通信)什麼是線程線程是作業系統調度的最小單元,在一個進程中可以創建多個線程,進程中的線程可以共享資源,但是每個線程都有自己的線程棧空間。Java運行是從main方法開始執行,會生成一個名為main線程。Java中的線程Java中的線程Thread類,是用來創建和啟動線程。使用方法Thread.start()來啟動一個線程。實現一個線程通常有這麼幾個方法。1、繼承Thread類,重寫run方法。執行start方法啟動線程。
  • Qt框架QThread類線程基礎知識
    什麼是線程?線程是並行執行操作,就像進程一樣。那麼,線程與進程有何不同呢?在電子表格上進行計算時,可能還有一個媒體播放器在同一桌面上播放您最喜愛的歌曲。下面是兩個並行工作的過程的示例:一個運行電子表格程序;一個運行媒體播放器。多任務處理是一個眾所周知的術語。仔細觀察媒體播放器後發現,在一個進程中,又發生了一些平行的事情。