1. 程式人生 > >挑戰408——作業系統(6)——執行緒詳解

挑戰408——作業系統(6)——執行緒詳解

20世紀80年代,人們提出了比程序更小,並能獨立執行的基本單位——執行緒。如果說程序的目的是為了讓多個程式彼此之間能夠併發執行,那麼引入執行緒就是為了減少併發執行所付出的時間和空間開銷。從而使得作業系統具有更好的併發性。

執行緒的作用

由於程序是一個資源的擁有者,因此在程序的建立,撤銷以及狀態轉換中都要付出巨大的時間和空間開銷。因此係統中的程序都不宜過多(開啟你們的工作管理員,執行的程序都能數出來),因為我們的主存空間是有限的。但這樣就很明顯的限制了併發程度的提高,因為可以執行的道數少了。
先回顧一下程序的兩個基本屬性

  1. 能擁有資源
  2. 可以獨立排程和分派的單位

若把這兩個屬性分開,那麼程序不再作為排程和分派的單位,將這一功能交給其他單位去完成,這個單位就是執行緒。執行緒是程序的一個實體同一個程序內可以訪問程序內部的所有資源(但不包括指向下一個程序的棧指標,因為它對執行緒透明)。而且執行緒中的通訊比程序中的通訊方便的多。
在這裡插入圖片描述
假設用方框表示程序,曲線表示執行緒,那麼上面的三個圖分別表示,單程序單執行緒,單程序多執行緒,多程序多執行緒。

執行緒與程序之間的區別與聯絡

類似於程序,每個程序都有一個執行緒控制塊(TCB),用於儲存自己私有資訊。而且執行緒的狀態,及其控制跟程序一樣。但是儘管如此相似,但是還是有所區別的。

  1. 一個程序至少擁有一個執行緒
    ,程序可以根據需要建立其他程序,也可以建立若干個執行緒。而執行緒雖然可以建立其他執行緒,但是不能建立程序。
  2. 程序是個擁有資源的獨立單位,而執行緒本身基本不擁有資源(只含有必不可少的資源,比如TCB和棧)。
  3. 在通訊方面程序中所有的執行緒共享該程序的所有資源在通訊方面程序中所有的執行緒共享該程序的所有資源,並駐留在同一地址空間,訪問相同的資料。但是程序只能通過同步,互斥來實現對共享資源的訪問
  4. 從排程的角度,在引入執行緒的作業系統中,執行緒是排程和分派的基本單位,程序是資源分配的基本單位。在同一個程序中,執行緒的切換不會引起程序的切換,只有在程序中一個執行緒切換到另一個程序的執行緒中的時候,才會引起程序的切換。
  5. 從系統開銷來說。在建立和撤銷程序的時候,作業系統所付出的時間和空間開銷將遠遠大於重建或者撤銷執行緒的開銷

執行緒的實現

我們知道,對於程序而言,無論是系統程序還是使用者程序,只要涉及程序的切換,在切換過程中都要依賴核心的程序排程程式。但是線上程中,這就不一定了。我們將執行緒的實現分為使用者級執行緒核心級執行緒

使用者級執行緒

下圖表示使用者級執行緒的實現方式:
在這裡插入圖片描述
在純粹實現使用者級執行緒的軟體中,有關執行緒管理的所有工作都由應用程式完成,應用程式和它所有的執行緒被分配到一個由核心管理的程序中,對於使用者級程序,一個程序內執行緒的行為不會影響其他程序,核心只是對程序進行適當的排程。

核心級執行緒

在這裡插入圖片描述
在僅有核心級執行緒的作業系統中,有關執行緒管理的所有工作都由核心完成,應用程式要想使用執行緒,只有通過核心提供的API系統的排程是基於執行緒的,也就是說,處理機的切換是以執行緒為單位進行的(所以執行緒是可以獨立執行的)。事實上,在核心級系統中,程序是資源的擁有者,執行緒是作為排程的基本單位,每個程序至少有一個執行緒。

兩者的區別

  1. 從切換速度來看,顯然使用者級執行緒的速度快,因為它不需要進入作業系統核心
  2. 當某一執行緒,使用者級執行緒阻塞,那麼對應的核心級執行緒也阻塞,其他可以併發執行的執行緒也必須阻塞(因為他們不能進入核心的那個程序中)。但是核心級執行緒卻不受此影響。

多執行緒的問題

問題一: 如何對多個執行緒進行取消?
答:多個執行緒執行同一個任務,其中一個執行緒任務完成,那麼剩餘的程序就應該取消(比如多個執行緒查詢某個檔案或者數字)。執行緒的取消是指在完成任務之前終止,分為立即取消和延遲取消兩種
問題二:如果每一個請求,便建立一個執行緒,那麼請求過多的時候,有限的系統資源就會被耗盡,那麼如何解決這一問題?
答:可以採用執行緒池的思想解決:

  1. 程序一開始時,建立一定量的執行緒,放入池中等待
  2. 收到請求後,喚醒其中的一個執行緒,並將要處理的請求傳遞給它。
  3. 執行緒完成任務返回池中等待
  4. 若沒有可用執行緒,那麼伺服器等待,直到出現空閒執行緒為止

(學過資料庫的同學應該知道,連線池的思想正是如此)

多執行緒模型

多執行緒模型是即實現使用者級執行緒,又實現核心級執行緒的一種連線方式。(0因此該模型一定同時支援使用者級執行緒和核心級執行緒)。也稱組合方式
在這裡插入圖片描述
(1) 多對一模型:這個模型實際上就是使用者級模型,多個使用者級對映到一個核心級執行緒,使用者級執行緒對作業系統是透明的。(也就是說當某個執行緒阻塞了,核心只是知道阻塞了,卻不清楚具體的情況。它只是負責呼叫)。顯然它存在一個執行緒阻塞,其他執行緒都阻塞的風險。
(2)一對一模型:將每個使用者級執行緒對映到一個核心級執行緒。這樣雖然確保了程序之間不會相互影響,但是建立的執行緒開銷很大。
(3)多對多模型:將n個使用者對映到m個核心級執行緒上(m<=n)