LinuxC++面向對象多線程學習筆記

LinuxC++面向對象多線程學習筆記_多任務與多線程編程


多任務(multitask)同時執行多個進程,而多線程(multithread)允許單個進程同時執行多個線程。

1. 多任務編程

當OS使用一個規劃策略允許兩個或更多進程併發共享一個CPU時,它稱做多任務編程(multitasking)或多程序編程(multiprogramming)。

多任務可以在3個級別上發生:

a. 對話級; b. 進程級; c. 線程級。

對話級的多任務由用戶控制。用戶運行若干應用程序或對話時發生用戶控制多任務(user-controlled multitask)。對話創建一個虛擬計算機以及它的鍵盤、鼠標和屏幕,當執行一個對話時,用戶可以決定切換到另一個對方中。因為由用戶決定哪一個應用或對話位於前臺或後臺,以及終止哪一個應用或對話,所以稱之為用戶控制多任務。用戶也可以打開新應用程序或對話。

在對話間,多個進程可以併發激活,通過相互合作來完成一個目標。當在一個對話中有多個進程激活時,這稱做進程級多任務編程(process-level multitasking)。

進程由多個單獨的任務組成,每個任務都有自己的控制流程,這些任務充當輕量級的進程即線程。進程內的多線程併發執行稱做多線程編程(multithreading)。

對話間的多任務是一個高級別的多任務,它受用戶所控制。進程間的多任務以及多線程在低級別上實現,並受到程序員的嚴重影響。程序員創建進程,並決定每個進程的線程數,還決定任務的優先權以及什麼時候掛起,什麼時候終止。

多任務的目的是增加系統完成的工作量。多任務通過保持資源(CPU,I/O等)的繁忙而且試圖防止它們在系統中處於非激活狀態來使用資源。大部分任務不能不間斷執行,因為它們需要等待I/O或另一個任務的終止,此時就可讓給其它任務來使用資源,以充分提高CPU的使用率。

2. 合作和搶佔式多任務

多任務使用兩種規劃原則來實現:合作(cooperation)與搶佔(preemption)。通過搶佔,OS保持對處理器的控制。一旦任務提交給處理器後,它只執行短暫的時間段,然後分配另一個任務給處理器。而通過合作,任務分配給處理器後,它就不能被搶佔。為了讓另一個任務執行,運行任務必須自願從處理器中刪除自身。

2.1 合作多任務

合作多任務允許任務控制處理器,OS放棄對處理器的控制,任務一旦擁有處理器就可以選擇運行任意長的時間而不會被系統操作搶佔,除非它自己放棄了控制權。在這樣的OS下,任何任務都可能發生飢餓。合作多任務使用優先權規劃。如果阻塞或掛起一個高優先權的任務,則低優先權任務被分配給處理器,它可以獨佔處理器,不允許高優先權任務有執行時間。

擁有處理器的任務可以在等待一個I/O請求完成時一直佔據處理器。系統依賴於任務間的合作來保持系統平穩運行。任務必須與所有的普通系統函數合作,否則這些函數就會受到侵犯,因為任務正佔據著處理器。

通過合作實現多任務的方式如下:

a. 設置它使用處理器的時間限制;

b. 在代碼中設置邏輯斷點,在此處放棄處理器;

c. 當發出I/O請求時放棄處理器;

d. 當系統操作需要立即執行時放棄處理器;

e. 放棄處理器允許交互任務使用處理器;

f. 放棄處理器允許系統對中斷作出反應。

合作多任務的優點如下:

a. 對時間重要任務和通信任務不會被搶佔;

b. 程序員控制了系統的操作;

c. 強迫程序員按防錯方式設計任務,有目的性地允許合作;

d. 任務的執行和反應更具可預測性;

e. 一種公平的規劃方法:引入的高優先權任務不能取代已經運行的任務;

f. 比搶佔式規劃開銷低,搶佔式規劃因為頻繁的上下文切換,所以需要在主存儲器中保持多個任務。

合作多任務的缺點:

a. 允許任務獨佔處理器;

b. 多任務只在任務得到處理器時才發生。由程序員決定是否發生多任務;

c. 可能得不到可接受的反應時間;

d. 程序員控制了系統的操作;

e. 程序員在設計任務時,必須考慮OS的操作,而不是排它性地設計任務的功能性;(無疑這樣對程序員的要求高了不少)

f. 沒有設計為合作的任務可以阻止正常合作任務的執行;

g. 長時間運行任務將使短時間運行任務等待;

h. 設計不良的任務可能導致整個系統停頓。

2.2 搶佔式多任務

搶佔式多任務是多任務的一種形式,在這種形式中,OS不會等到任務自願將處理器交還系統,讓它分配另一個任務給處理器。每個任務運行短暫的一段時間,稱為時間片斷(slice)或時間片(quantum),當時間片過期時,OS搶佔執行並分配另一個任務給處理器。任務在時間段過期前,可以自願放棄處理器;但如果仍然執行,則該任務會被刪除。

搶佔式多任務的優點:

a. 不允許任何任務獨佔處理器;

b. 設計不良的任務不限止其它任務的執行,而且不導致整個系統的停頓,因為它們將被搶佔;

c. OS保持對系統的控制;

d. 設計任務時,程序員不必考慮系統的操作,而可以排它性地設計任務的功能性;

e. 通過分配每個任務一段處理器時間來推進任務的執行;

f. 由於上下文的切換,所以有可接受的反應時間;

g. 新引入的高優先權可以搶佔運行任務;

h. 多任務由OS執行,而不是由程序員來執行。

搶佔式多任務的缺點:

a. 時間敏感任務和通信可能被搶佔;

b. 比合作式多任務開銷大,因為頻繁的上下文切換,所以必須在主存儲器中保持多個任務。

2.3 時間片的大小

如果時間片太長,一旦某個任務得到處理器,它就執行到完成,而不是多任務地執行,系統操作性能就會降級到連續性執行;而如果時間片過短,開銷變得更為重要。時間片的長度隨系統的不同而不同,在不同的條件下也可能發生變化,還可能針對不同類型的任務而有所不同。

一些OS允許更改時間片的長度。時間片有一個最小值和一個最大值,以毫秒為單位。用戶按這種方式定義後,它就成為一個靜態值。缺省時間片為動態,根據系統裝載的不同,時間片的大小也會改變。對於允許這種變化的系統,在文件config.sys中定義時間片的大小。

3. 多處理器下的多線程

非對稱和對稱系統都處於一種緊密耦合(tightly coupled)環境中。緊密耦合環境意味著,處理器處於一種使用單一操作系統控制所有處理器的單一系統中。這些處理器有一個用於通信的共享內存區域,只要在這裡存在共享的內容,就有可能存在對它的競爭。通過在處理器間分佈任務裝載、使用阻塞或每個處理器的緩衝內存,可以將這種競爭降到最低限度。

緊密耦合環境與鬆散耦合環境相反。在鬆散耦合環境中,存在兩個或更多的獨立系統,它們各自有自己的存儲器和操作系統。這種系統通過消息傳遞或遠程過程建立通信鏈接,相互間可以訪問對方的文件。在緊密耦合環境中,處理器訪問相同的就緒隊列。在鬆散環境中,獨立系統保持有自己的單獨就緒隊列。單個進程的線程可以利用緊密耦合的多處理器。

3.1 非對稱多處理器處理

在非對稱組織的多處理器處理系統中,一個處理器執行一個設計好的任務。設計用一個處理器(譬如處理器0)一執行輸入和輸出,其它處理器(譬如處理器1到處理器n)執行計算密集型的任務。只要需要執行I/O,就用處理器0來執行,它只執行操作系統,而用戶任務不能在執行OS所在的處理器上執行。非對稱多處理器處理用於非對稱硬件上,例如一個處理器和一個協理器(coprocessor)。

非對稱多處理器給其上的每個處理器進行了職能劃分,限定了其分別所可執行任務的種類,因此它允許處理器處理空閒(即使有任務在等待執行),所以整體上減少了處理器的吞吐量。

3.2 對稱多處理器處理

多處理器對稱組織具備一個相互等同的處理器池(pool of processor)。處理器不是設計用於執行特殊類型的任務。任何處理器都可以執行系統或用戶線程,都可以控制某個I/O設備或引用內存地址。操作系統線程可在任何處理器上執行,而且從一個處理器漂移到另一個處理器上,所以操作系統代碼需要重新進入。某些系統有一個設計作為執行處理器的處理器,它負責系統數據和系統函數。對稱多處理器處理是一種更穩固、可靠的環境,如一個崩潰,它就不再屬於可用處理器之列了。

3.3 具有多處理器的多線程處理模型

創建具有同時執行多線程的進程強迫程序員按並行的方式來思考,程序員必須考慮在同一時刻所有執行的形為,以及它們之間相互影響的方式,或者一些全局結構。同時執行的任務可以相互獨立發揮作用,或者在某個點,可能需要其它任務的同步或合作。需求同步化時,該任務可能不能繼續執行,直到其中一個任務完成為止。需求合作可能意味著該任務從其它將完成工作的任務中獲取一些數據。完成與其它任務獨立發揮作用的同時(simultaneous)任務則不需要同步(synchronization)。事實上,它們可以不按特定的順序來執行。

容易將完全獨立的線程分配給它們自己的處理器來執行。其它任務可能需要一定程度的同步和合作。需要用一個範例為併發任務建立模型。模型將特徵化如何將工作分解成線程,以及線程如何同步化。模型應當包含數據結構中的任何共享數據,使用某種類型的阻塞機制可以保護這些數據結構,使訪問同步化而避免數據競爭。

在多處理器處理環境中,一個用於多線程進程的模型例子是主-次線程模型(primary-secondary thread model)。在這個模型中,一個線程(指主線程)將任務分解,並分佈到次線程中。這些次線程在同一時間調用。主線程一直等到所有的次線程都完成了它們的任務,然後才繼續。主線程與次線程同步執行。主線程根據事先知道的工作調用線程,將工作大體平分為相等的部分。

管道線模型:工作分為幾個執行階段。這些階段創建一個管道線或裝配線,在每個階段執行指定的任務部分。管道線中的每個階段執行不同或相同任務。這些階段並行執行。在管道線中為每個階段分配一個線程。

工作堆:分配任務以隊列形式存在於工作堆中的多個塊。工作線程從堆中請求任務來執行。可以給工作堆添加工作線程。請求可以得到保證,直到工作堆為空。工作堆不同於主-次線程模型,主-次模型需要預先知道將要完成的工作量,然後創建相應數量的次線程。而在工作堆模型中,預告不知道工作量,工作線程可能導致執行額外的任務。

4. 規劃策略

規劃策略決定什麼時候分配處理器,以及分配哪一個線程給處理器。OS可能使用優先權規劃,其中最高優先權線程被分配給處理器。當存在多個同一優先類(或)優先級的線程時,使用另一個規劃方案。

規劃的發生級別有:

a. 線程規劃;

b. 進程規劃;

c. 中間級規劃。

像進程、線程這樣的低級別規劃由分派器來執行(分派器常駐在主存儲器中)。中間級別規劃決定允許哪一個進程競爭處理器。競爭處理器的進程保存在就緒隊列中。在這一級別,進程可以掛起,由於系統負載的變化也可能恢復。這個級別的規劃是進入系統的進程與競爭處理器進程之間的一個緩衝器。

規劃策略的目的是決定哪一個進程或線程使用處理器以及應當何時使用處理器。它應當偏向於佔有重要資源的任務。低優先權任務可能鎖定資源,而這些資源將被其它具有較高優先權任務所使用或被系統中的許多激活任務所使用,因此可能會導致死鎖。這種規劃機制應當偏向於鎖定這類資源的進程或線程,使得它可以釋放資源。

規劃策略目標:

a. 最大化吞吐量;

b. 強制優先權;

c. 根據實際,儘量公平;

d. 最小化開銷;

e. 避免無限延遲和飢餓;

f. 偏向於佔據了其它任務所需資源的任務;

g. 在需要時,有充足的可用資源,讓反應時間可接受;

h. 不應當在重系統負荷下崩潰。

常用的規劃策略如以下:

FIFO(非搶佔式);SJF(最短任務優先,同樣非搶佔式);RR(輪詢,搶佔式的);STR(最短剩餘時間,也是搶佔式的),HRN(最高反應率其次,非搶佔式的)。

更多面試資料與學習視頻與筆記微信搜索關注零聲學院公眾號領取!!


LinuxC++面向對象多線程學習筆記_多任務與多線程編程

LinuxC++面向對象多線程學習筆記_多任務與多線程編程


分享到:


相關文章: