1. 程式人生 > >作業系統概念(第四章) 執行緒

作業系統概念(第四章) 執行緒

執行緒

概述

概述

單個程序可以包括多個控制執行緒。

執行緒 ——一種CPU利用的基本單元,它是形成多執行緒計算機的基礎。

執行緒是CPU使用的基本單元,它由執行緒ID、程式計數器、暫存器集合和棧組成。它與屬於統一程序的其他執行緒共享程式碼段_資料段其他作業系統資源

一個傳統重量級的程序只有單個控制執行緒,如果程序有多個控制執行緒,那麼能同時做多個任務。

動機

一個應用程式通常是作為一個具有多個控制執行緒的獨立程序實現的。如一個忙碌的網頁伺服器如果有多個(或數千個)客戶併發訪問它,可以建立多個執行緒而非程序,因為建立程序很耗時間,而單個執行緒的程序一次只能處理一個請求。

執行緒在遠端過程呼叫(RPC)系統中個也有很重要的作用,通常,PRC伺服器是多執行緒的。當一個伺服器接收到訊息,它使用獨立執行緒處理訊息,這允許伺服器能處理多個併發請求。

現代許多作業系統都是多執行緒的,少數執行緒在核心中執行,每個執行緒完成一個指定的任務。

多執行緒的優點

  1. 響應度高(Responsiveness):即使其部分阻塞或執行較冗長操作,該程式仍能繼續執行,從而增加了對使用者的相應程度。

  2. 資源共享(Resource Sharing):執行緒預設共享它們所屬程序的記憶體和資源。程式碼和資料共享的優點是它允許一個應用程式在同一地址空間有多個不同的活動執行緒。

  3. 經濟(Economy):程序建立所需要的記憶體和資源的分配比較昂貴。由於執行緒能共享它們所屬程序的資源,所以建立和切換執行緒會更為經濟。

  4. 多處理器體系結構的利用(Utilization of MP Architectures):多執行緒的優點之一是能充分使用多處理器體系結構。以便每個程序能並行執行在不同的處理器上。不管有多少CPU,單執行緒程序只能執行在一個CPU上,在多CPU上使用多執行緒加強了併發功能。

多執行緒模型

有兩種不同的方法來提供執行緒支援:使用者層的使用者執行緒(User Threads)和核心層的核心執行緒。使用者執行緒受核心支援,而無需核心管理;而核心執行緒由作業系統支援和管理。事實上所有當代作業系統都支援核心執行緒。在使用者執行緒和核心執行緒之間必然存在一種關係。

多對一模型:

多對一模型將許多使用者級執行緒對映到一個核心執行緒。執行緒管理由執行緒庫在使用者空間進行的,因而效率比較高。但是如果一個執行緒執行了阻塞系統呼叫,那麼整個執行緒會阻塞。因為任意時刻只能有一個執行緒能夠訪問核心,多個執行緒不能並行執行在多處理器上。

這裡寫圖片描述

一對一模型:
一對一模型每個使用者執行緒對映到一個核心執行緒。該模型在一個執行緒執行阻塞系統呼叫時,能允許另一個執行緒繼續執行。它也允許多個執行緒能並行執行在多處理器系統上,這種模型的唯一缺點是每建立一個使用者執行緒就會建立一個相應的核心執行緒。由於建立核心執行緒的開銷會影響應用程式的效能,所以這種模型的絕大多數實現限制了作業系統所支援的執行緒數量。

這裡寫圖片描述

多對多模型:

多對多模型多路複用了許多使用者執行緒到同樣數量或更小數量的核心執行緒上。多對多模型沒有這兩者的缺點:開發人員可建立任意多的使用者執行緒,並且相應核心執行緒能在多處理器系統上併發執行。而且當一個執行緒執行阻塞系統呼叫時,核心能排程另一個執行緒來執行。

一個流行多對多模型的變種仍然多路服用了許多使用者執行緒到同樣數量或更小數量的核心執行緒上,但也允許將一個使用者執行緒繫結到某個核心執行緒上。這個變種有是被稱為二級模型。

這裡寫圖片描述

多執行緒問題

系統呼叫fork()和exec()

在多執行緒程式中,系統呼叫fork()和exec()的語義有所改變。

如果程式中一個程序呼叫fork(),那麼新程序會複製所有執行緒,還是新程序只有單個執行緒?有的UNIX系統有兩種形式的fork(),一種複製所有執行緒,另一種只複製呼叫了系統呼叫fork()的執行緒。

Exec()工作方式:如果一個執行緒呼叫系統呼叫exec(),那麼exec()引數所指定的程式會替換整個程序,包括所有執行緒。

如果呼叫fork()之後立即呼叫exec(),那麼沒有必要複製所有執行緒,因為exec()引數所指定的程式會替換整個程序。在這種情況下,只複製呼叫執行緒比較適當。不過,如果在fork()之後另一程序並不呼叫exec(),那麼另一程序就應複製所有程序。

取消

執行緒取消(thread cancellation)是線上程完成之前來終止執行緒的任務。

要取消的執行緒通常稱為目標執行緒。目標執行緒的取消可在如下兩種情況下發生:

一是非同步取消(asynchronous cancellation):一個執行緒立即終止目標執行緒。

二是延遲取消(deferred cancellation):目標執行緒不斷地檢查它是否應終止,這允許目標執行緒有機會以有序方式來終止自己。

如果資源已經分配給要取消的執行緒,或者要取消的執行緒正在更新與其他執行緒所共享的資料,那麼取消會有困難,對於非同步取消尤為麻煩。作業系統回收取消執行緒的系統資源,但是通常不回收所有資源。因此,非同步取消執行緒並不會使所需的系統資源空閒。相反採用延遲取消時,允許一個執行緒檢查它是否是在安全的點被取消,pthread稱這些點為取消點(cancellation point)

訊號處理

訊號處理:訊號在Unix中用來通知程序某個特定時間已發生了,訊號可以同步或非同步接收。所有有訊號具有同樣的模式:

(1)訊號有特定事件的發生所產生

(2)產生的訊號要傳送到程序

(3)一旦傳送,訊號必須交易處理。

同步訊號的例子包括訪問非法記憶體或被0除。在這種情況下,如果執行程式執行這些動作,那麼就產生訊號,同步訊號傳送到執行操作而產生訊號的同一程序(同步的原因)。

當一個訊號由執行程序之外的事件產生,那麼程序就非同步接收這一訊號。這種訊號的例子包括使用特殊鍵(Ctrl + C)或者定時器到期。通常,非同步訊號被髮送到另一個程序。

每個訊號可能由兩種可能的處理程式中的一種來處理:

(1)預設訊號處理程式

(2)使用者定義的訊號處理程式

每個訊號都有一個預設訊號處理程式,當處理訊號是在核心中執行的,這種預設動作可以用使用者定義的訊號處理程式來改寫。訊號可以按照不同的方式處理。有的訊號可以簡單的忽略(如改變視窗大小),有的需要終止程式來處理(非法記憶體訪問)

單執行緒程式的訊號處理比較直接,訊號總是傳送給程序。

當多執行緒時,訊號會

(1)傳送訊號到訊號所應用的執行緒

(2)傳送訊號到程序內的每個執行緒

(3)傳送訊號到程序內的某些固定執行緒

(4)規定一個特定執行緒以接收程序的所有訊號。

傳送訊號的方法依賴於訊號的型別。

大多數執行緒版Unix允許執行緒描述它會接收什麼訊號和拒絕什麼訊號。,因為訊號只能處理一次,所以訊號通常傳送到不拒絕它的第一個執行緒。

pthread還提供了pthread_kill函式,此函式允許限號被傳送到一個指定執行緒。

Windows,通過非同步過程呼叫(asynchronous procedure call,APC)來模擬訊號。

執行緒池

多執行緒伺服器有一些潛在問題:第一個是關於處理請求之前用以建立執行緒的時間,以及執行緒在完成工作之後就要被丟棄這一事實。第二個,如果允許所有併發請求都通過新執行緒來處理,那麼將沒法限制在系統中併發執行的執行緒的數量。無限制的執行緒會耗盡系統資源。解決這一問題是使用執行緒池。

執行緒池的思想是在程序開始時建立一定數量的執行緒,並放入到池中以等待工作。當伺服器收到請求時,他會喚醒池中的一個執行緒,並將要處理的請求傳遞給他,一旦執行緒完成了服務,它會返回到池中在等待工作。如果池中沒有可用的執行緒,那麼伺服器會一直等待直到有空執行緒為止。

執行緒池的優點:

(1)通常用現有執行緒處理請求要比等待建立新的執行緒要快

(2)執行緒池限制了在任何時候可用執行緒的數量。

執行緒池中的執行緒數量由系統CPU的數量、實體記憶體的大小和併發客戶請求的期望值等因素決定。比較高階的執行緒池能動態的調整執行緒的數量,以適應具體情況。

執行緒特定資料

同屬一個程序的執行緒共享程序資料。

在某些情況下每個執行緒可能需要一定資料的自己的副本,這種資料稱為執行緒特定資料。可以讓每個執行緒與其唯一的識別符號相關聯。

排程程式啟用

核心與執行緒庫的通訊問題,就是要討論多對多模型。這種協調允許動態調整核心執行緒的數量以保證其最好的效能。

在使用者核心執行緒之間設定一種中間資料結構。輕量級程序(LWP),他表現為一種應用程式可以排程使用者執行緒來執行的虛擬處理器。每個LWP與核心執行緒相連,該核心執行緒被作業系統排程到物理處理器上執行,如果核心執行緒阻塞,LWP阻塞,與LWP相連的使用者執行緒也阻塞。如果在單處理器上,一次只能執行一個執行緒,則只需要一個LWP就夠了,但I/O密集的應用程式可能需要多個LWP來執行。

一種結局使用者執行緒庫與核心間通訊的方法為排程器啟用(scheduler activation),核心提供一組虛擬處理器(LWP)給應用程式,應用程式可排程使用者程序到一個可用的虛擬處理器上。