c++11中thread join和detach的區別


線程狀態:

在一個線程的生存期內,可以在多種狀態之間轉換,不同的操作系統可以實現不同的線程模型,定義許多不同的線程狀態,每個狀態還可以包含多個子狀態,但大體來說,如下幾種狀態是通用的:

1)就緒:參與調度,等待被執行,一旦被調度選中,立即開始執行

2)運行:占用CPU,正在運行中

3)休眠:暫不參與調度,等待特定事件發生

4)中止:已經運行完畢,等待回收線程資源

線程環境:

線程存在於進程之中,進程內所有全局資源對於內部每個線程都是可見的。

進程內典型全局資源如下:

1)代碼區:這意味着當前進程空間內所有的可見的函數代碼,對於每個線程來說,也是可見的

2)靜態存儲區:全局變量,靜態空間

3)動態存儲區:堆空間

線程內典型的局部資源:

1)本地棧空間:存放本線程的函數調用棧,函數內部的局部變量等

2)部分寄存器變量:線程下一步要執行代碼的指針偏移量

一個進程發起后,會首先生成一個缺省的線程,通常稱這個線程為主線程,C/C++程序中,主線程就是通過main函數進入的線程,由主線程衍生的線程成為從線程,從線程也可以有自己的入口函數,相當於主線程的main函數,這個函數由用戶指定。通過thread構造函數中傳入函數指針實現,在指定線程入口函數時,也可以指定入口函數的參數。就像main函數有固定的格式要求一樣,線程的入口函數也可以有固定的格式要求,參數通常都是void類型,返回類型根據協議的不同也不同,pthread中是void,winapi中是unsigned int,而且都是全局函數。

最常見的線程模型中,除主線程較為特殊之外,其他線程一旦被創建,相互之間就是對等關系,不存在隱含的層次關系。每個進程可創建的最大線程數由具體實現決定。

無論在windows中還是Posix中,主線程和子線程的默認關系是:無論子線程執行完畢與否,一旦主線程執行完畢退出,所有子線程執行都會終止。這時整個進程結束或僵死,部分線程保持一種終止執行但還未銷毀的狀態,而進程必須在其所有線程銷毀后銷毀,這時進程處於僵死狀態。線程函數執行完畢退出,或以其他非常方式終止,線程進入終止態,但是為線程分配的系統資源不一定釋放,可能在系統重啟之前,一直都不能釋放,終止態的線程,仍舊作為一個線程實體存在於操作系統中,什么時候銷毀,取決於線程屬性。在這種情況下,主線程和子線程通常定義以下兩種關系:

1、可會合(joinable):這種關系下,主線程需要明確執行等待操作,在子線程結束后,主線程的等待操作執行完畢,子線程和主線程會合,這時主線程繼續執行等待操作之后的下一步操作。主線程必須會合可會合的子線程。在主線程的線程函數內部調用子線程對象的wait函數實現,即使子線程能夠在主線程之前執行完畢,進入終止態,也必須執行會合操作,否則,系統永遠不會主動銷毀線程,分配給該線程的系統資源也永遠不會釋放。

2、相分離(detached):表示子線程無需和主線程會合,也就是相分離的,這種情況下,子線程一旦進入終止狀態,這種方式常用在線程數較多的情況下,有時讓主線程逐個等待子線程結束,或者讓主線程安排每個子線程結束的等待順序,是很困難或不可能的,所以在並發子線程較多的情況下,這種方式也會經常使用。

在任何一個時間點上,線程是可結合(joinable)或者是可分離的(detached),一個可結合的線程能夠被其他線程回收資源和殺死,在被其他線程回收之前,它的存儲器資源如棧,是不釋放的,相反,一個分離的線程是不能被其他線程回收或殺死的,它的存儲器資源在它終止時由系統自動釋放。

線程的分離狀態決定一個線程以什么樣的方式來終止自己,在默認的情況下,線程是非分離狀態的,這種情況下,原有的線程等待創建的線程結束,只有當pthread_join函數返回時,創建的線程才算終止,釋放自己占用的系統資源,而分離線程沒有被其他的線程所等待,自己運行結束了,線程也就終止了,馬上釋放系統資源。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM