操作系統原理第四章:線程

1 線程的引入

1.1 線程的由來

前面章節提到,引入進程是爲了解決程序併發所出現的一些問題,進程具有兩個基本的屬性:

  • 進程是一個擁有資源的獨立單位:它可獨立分配虛地址空間、主存和其它;
  • 進程是一個可獨立調度和分派的基本單位。

正是因爲進程具有這兩個基本屬性,所以進程成爲併發執行的基本單位, 在一些早期的OS中,比如大多數UNIX系統、Linux等,進程同時具有這二個屬性,由於 進程是一個資源的擁有者 ,因而在進程創建、撤銷、調度切換時,系統需要付出較大的時空開銷,所以進程的數目不宜過多,進程切換頻率不宜過高,否則會限制併發程度,操作系統的設計目標是提高併發度,減小系統開銷,顯然進程還不能做到完全的高效,所以引入了線程的概念。

那麼有沒有一種方法能夠既提高系統併發,還能減少系統開銷呢,我們採用的方法是將進程的兩個基本屬性分開,對於擁有資源的基本單位,不對其進行頻繁切換,對於調度的基本單位,不作爲擁有資源的單位,“輕裝上陣”,引入線程以小的開銷來提高進程內的併發程度。

在沒有引入線程之前,進程作爲資源分配單位(存儲器、文件)和CPU調度單位。當引入線程後把線程作爲作爲CPU調度單位,而進程只作爲其他資源分配單位。相比進程,線程只擁有必不可少的資源,如:線程狀態、程序計數器、寄存器上下文和棧,線程同樣具有就緒、阻塞和執行三種基本狀態,一個進程可以創建多個線程,線程與同屬一個進程的其它線程共享進程擁有的全部資源,並且這些線程可以併發執行。

1.2 線程的特點

減小併發執行的時間和空間開銷(線程的創建、退出和調度),因此容許在系統中建立更多的線程來提高併發程度,因爲線程有如下特點:

  • 線程的創建時間比進程短;
  • 線程的終止時間比進程短;
  • 同進程內的線程切換時間比進程短;
  • 由於同進程內線程間共享內存和文件資源,可直接進行不通過內核的通信;
  • 一個多線程的應用在執行中,即使其中的某個線程阻塞,其他的線程還可繼續執行,從而提高響應速度
  • 同一進程的多個線程共享該進程的內存等資源
  • 創建和切換線程的開銷要低於進程。比如,Solaris中進程創建時間是線程創建的30倍,進程切換時間是線程切換的5倍
  • 多線程更適用於多處理機結構

1.3 線程的定義

線程(輕型進程)是CPU運用的一個基本單元,包括:

  • 程序計數器 (program counter)
  • 寄存器集 (register set)
  • 棧空間 (stack space)

一個線程與它的對等線程共享如下內容:

  • 代碼段 (code section)
  • 數據段 (data section)
  • 操作系統資源 (operating-system resources)

傳統的或重型進程等價於只有一個線程的任務,下圖是單線程和多線程的對比,可以從圖中看到多個線程共享code,data,files,並且每個線程有自己的registers,stack
在這裏插入圖片描述

1.4 進程和線程的比較

  • 併發性:在引入線程的OS中,不僅進程之間可以併發執行,而且在一個進程中的多個線程之間亦可併發執行,因而使OS具有更好的併發性,從而能更有效地使用系統資源和提高系統吞吐量;
  • 擁有資源:進程是擁有資源的獨立單位,而線程只擁有一些必不可少的資源;
  • 系統開銷:在創建或撤消進程時,系統都要爲之分配或回收資源,如內存空間、I/O設備等。因此,OS所付出的開銷將明顯地大於在創建或撤消線程時的開銷;
  • 地址空間和其他資源(如打開文件):進程間相互獨立,同一進程的各線程間共享,某進程內的線程在其他進程不可見;
  • 通信:進程間通信IPC,線程間可以直接讀寫進程數據段(如全局變量)來進行通信,需要進程同步和互斥手段的輔助,以保證數據的一致性;
  • 調度:線程上下文切換比進程上下文切換要快得多,下圖是線程切換和進程切換的示意圖,當單線程進程需要切換的時候,整塊內容都需要切換,當多線程進行切換的時候,只需要切換單個線程內容,即虛線框內的內容。
    在這裏插入圖片描述

2 內核線程和用戶線程

線程是一個輕型的進程,引入線程是爲了進一步提高系統併發,從而提高系統效率,線程在實現的時候分爲兩種:

  • 內核支持的線程 (Kernel-supported threads)
  • 用戶級線程 (User-level threads):在內核之上,通過用戶級的庫調用

2.1 內核線程

內核線程由內核支持,在內核空間執行線程創建、調度和管理,當線程是內核線程時,才真正的是CPU調度的基本單位,這麼說是因爲後面要講到的用戶線程並不是CPU調度的基本單位。內核線程是依賴於操作系統的,這個時候內核維護進程和線程的上下文信息,線程切換由內核完成,一個線程發起系統調用而阻塞,不會影響其他線程的運行,時間片分配給線程,所以多線程的進程獲得更多CPU時間(線程作爲CPU調度的基本單位,每個線程都會分得時間片,所以線程越多的進程,分到的CPU時間越多)。

2.2 用戶線程

用戶線程是由用戶級線程庫進行管理的線程,這個時候線程庫提供對線程創建\調度和管理的支持,無需內核支持,因此用戶線程不是CPU調度的基本單位,此時進程是CPU調度的基本單位。

由於用戶線程不依賴於 OS 核心,應用進程利用線程庫提供創建、同步、調度和管理線程的函數來控制用戶線程。調度由應用軟件內部進行,通常採用非搶先式和更簡單的規則,也無需用戶態核心態切換,所以速度特別快 。

用戶線程的維護由應用進程完成,內核不瞭解用戶線程的存在,用戶線程切換不需要內核特權,用戶線程的缺點是如果內核是單線程的,那麼一個用戶線程發起系統調用而阻塞,則整個進程阻塞,此時時間片分配給進程,多線程則每個線程就慢。

2.3 兩者比較

  • 調度方式:內核線程的調度和切換與進程的調度和切換十分相似,用戶線程的調度不需OS的支持;
  • 調度單位:用戶線程的調度以進程爲單位進行,在採用時間片輪轉調度算法時,每個進程分配相同的時間片。對內核級線程,每個線程分配時間片

3 線程模型

用戶線程是在用戶空間去實現的,有關於用戶線程的所有操作都是在用戶空間裏實現的,那麼這樣的用戶線程如果要用到操作系統提供的功能的時候,它通常是要映射到內核空間去,就要在用戶線程和內核線程之間做映射,在映射過程中有以下三種模式:

  • 多對一 (Many-to-One):多個用戶線程映射到內核線程上,如下圖,任一時刻只能有一個線程可以訪問內核(併發性低),一個用戶線程發起系統調用而阻塞,則整個進程阻塞:
    在這裏插入圖片描述
  • 一對一 (One-to-One):每個用戶線程對應一個內核線程,如下圖,提供了更好的併發性,一個用戶線程發起系統調用而阻塞時允許另一個線程運行,每創建一個用戶級線程需創建一個相應的內核線程,帶來了額外開銷,所以許多系統限制應用中的線程數目:
    在這裏插入圖片描述
  • 多對多 (Many-to-Many):爲了克服上述兩種方式的缺點,引入了多對多模型,不限制應用的線程數、多個線程可以併發,如下圖:
    在這裏插入圖片描述
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章