關於線程的執行和退出

來源:互聯網
上載者:User

線程由兩部分構成:

線程核心對象:作業系統用它來對線程實施管理。核心對象也是系統用來存放線程統計資訊的地方。

線程堆棧:它用於維護線程在執行代碼時需要的所有函數參數和局部變數。

 

我們必需要知道一個事實
-----
進程(
WINDOWS
中)是不能被調度的。通常所說的調度,都是對線程而言的。進程僅僅是線程的容器,是系統統分配資源的單位。
這樣,線程自身不會分配資源。同一進程中的多個線程共同使用它們父進程的資源。

 

一個進程至少需一個線程,如果一個進程中不存線上程(所有線程都退出)。則系統認為這個進程沒有存在的必要,於是便會撤消這個進程,並釋放他佔用的資源。

 


VC
環境中,我們可以調用
CreatThread
來建立一個線程。關於用法請查
MSDN

我們應該主要關注這個
API
的調用,作業系統會幹哪些事情。而不是僅僅會使用這個
API

 

當程式啟動的時候,系統會建立一個進程,進而會為這個進程建立一個主線程。主線程即是一個程式的入口。
C/C++
運行期庫會初始化全域的
C/C++
變數,然後調用進入點函數(如
main
)。然後初始化線程堆棧,建立臨時變數等。

 

當線程結束時會按以下操作執行。

1、     

線上程函數中建立的所有
C++
對象均將通過它們的撤消函數正確地撤消。

2、     

作業系統將正確地釋放線程堆棧使用的記憶體。

3、     

系統將線程結束代碼設定為線程函數的傳回值。

4、     

系統將遞減線程核心對象的引用計數。

 

因此,正確的線程退出方式是必不可少的。
最好的退出線程的方法是讓線程函數返回,這樣
C/C++
運行期庫便能正確地撤消
C/C++
對象。
值一說的是,不管線程怎麼退出,當一個程式結束時,系統總是回清除他使用了的系統資源,如核心對象等。但
C/C+=
運行期庫申請的資源則不會被釋放。

 


ExitThread
等函數,需要三思而用。

 

眾所周知,建立線程的時候,必不可少的兩個參數就是線程入口函數和函數參數。那這兩個是怎麼工作的呢。請看如下分析。

 

首先要知道,每個線程都有自己的一組
CPU
寄存器。這組寄存器的所有資訊就是我們所說的線程上下文。當系統進行時間片輪轉執行線程的時候,會將前一個線程的所有寄存器值儲存,然後將下一個需要執行的線程的寄存器值裝入
CPU
寄存器,進而執行。重複這樣的操作,就達到了多線程執行的效果。當然,實際情況是很複雜的。需要許多的判斷,在多處理器電腦中,還需要考慮線程的親緣性等。

 

話不多說,回頭來看這個線程函數的執行方式。

當一個線程被建立時,系統便會建立線程的核心對象。並分配線程堆棧需要的記憶體。這個記憶體是從進程的地址空間分配而來的,因為我們知道,線程不持有資源。當一切都做好後,便是填寫資料了。

 

系統首先會把線程的參數和入口地址壓入線程堆棧。
注意,是先壓的參數,再壓的入口地址。這樣入口地址是在棧頂。此時
SP
的值即為函數入口地址。
而將
IP
設定為另一個函數。它叫
void BaseThreadStart();
很神奇吧,為什麼
IP
並不是線程的入口函數地址呢。
我們直接可以猜到,
void BaseThreadStart();
所做的工作中,會調用到我們的線程入口函數。接下來我們看看
void BaseThreadStart();
函數幹了些什麼。

void BaseThreadStart(PTHREAD_START_ROUTINE pfnStartAddr,PVOID pvParam)

{

  __try{

Exithread((pfnStartAddr)(pvParam));

}

__except(UnhandedExceptionFilter(GetExceptionInformation()){

ExitProcess(GetExceptionCode());

}

}

 

還記得我們壓棧的時候是先壓的參數再壓的線程函數入口地址麼。這就對了,上面即是這樣的情況。
可以看出,
BaseThreadStart
函數不會馬上返回,他會等待線程結束後返回。由於線程和進程共用的進程記憶體空間,可以知道。如果線程函數沒有退出
BaseThreadStart
就返回,可以肯定的會引發訪問違規。因為線程未退出時,線程堆棧並未清除。
BaseThreadStart
返回時,從堆棧上得到的返回地址是一個不可預測的值。
進程在初始化時也會是類似執行方式。因為進程執行時,啟動的是一個主線程,而不是由進程本身來執行代碼。

 

最後說明,當新線程執行
BaseThreadStart
函數時,將會出現如下情況:

1、     

線上程函數中建立一個
SHE
,這樣,線上程執行時產生的任何異常情況都將會得到系統的某種預設處理。

2、     

系統調用線程函數,並將你傳遞的參數傳遞給它。

3、     

當線程函數返回時,
BaseThreadStart
調用
Exithread
,並將線程函數的傳回值傳遞給它。該線程核心對象的使用計數減
1
,線程停止運行。

4、     

如果線程產生一個沒有處理的異常條件,由
BaseThreadStart
建立的
SHE
將負責處理該異常。由上面可以看出,它調用
ExitProcess
退出整個進程。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.