讓醫(yī)院做網(wǎng)站的策劃書國外免費網(wǎng)站建設(shè)
一、什么是線程?
???????線程是“輕量級進程”,是進程中的?個實體,是程序執(zhí)?的最小單元,也是被系統(tǒng)獨立調(diào)度和分配的基本單位。
????????線程是進程當中的?條執(zhí)行流程,同?個進程內(nèi)多個線程之間可以共享代碼段、數(shù)據(jù)段、打開的文件等資源,但每個線程各自都有?套獨立的寄存器和棧,這樣可以確保線程的控制流是相對獨立的。
二、線程的優(yōu)缺點
線程的優(yōu)點:
- 一個進程中可以同時存在多個線程;
- 各個線程之間可以并發(fā)執(zhí)行;
- 各個線程之間可以共享地址空間和文件等資源;
線程的缺點:
- 當進程中的一個線程崩潰時,會導致其所屬進程的所有線程崩潰
三、進程、線程和協(xié)程區(qū)別
進程 | 線程 | 協(xié)程 | |
定義 | 資源分配和擁有的基本單位 | 程序執(zhí)行的基本單位 | 用戶態(tài)的輕量級線程 |
切換情況 | ? ? ?保存和設(shè)置進程CPU環(huán)境(棧、寄存器、頁表和文件句柄) | 保存和設(shè)置程序計數(shù)器、少量寄存器和棧 | 先將寄存器上下文和棧保存,等切換回來的時候再進行恢復(fù) |
切換者 | 操作系統(tǒng) | 操作系統(tǒng) | 用戶 |
切換過程 | 用戶態(tài)->核心態(tài)->用戶態(tài) | 用戶態(tài)->核心態(tài)->用戶態(tài) | 用戶態(tài) |
調(diào)用棧 | 內(nèi)核棧 | 內(nèi)核棧 | 用戶棧 |
擁有資源 | CPU資源、內(nèi)存資源、文件資源和句柄等 | 程序計數(shù)器、寄存器、棧和狀態(tài)字 | 擁有自己的寄存器上下文和棧 |
并發(fā)性 | 不同進程之間切換實現(xiàn)并發(fā),各自占有CPU實現(xiàn)并行 | 一個進程內(nèi)部的多個線程并發(fā)執(zhí)行 | 同一時間只能執(zhí)行一個協(xié)程,其他協(xié)程處于休眠狀態(tài),適合對任務(wù)進行分時處理 |
系統(tǒng)開銷 | 切換虛擬機地址空間,切換內(nèi)核棧和硬件上下文,開銷大 | 切換時只需保存和設(shè)置很少量的寄存器內(nèi)容,開銷小 | 直接操作棧,基本沒有內(nèi)核切換開銷,可以不加鎖的訪問全局變量,上下文切換速度非???/span> |
通信方面 | 需要借助操作系統(tǒng)(管道、消息隊列、共享內(nèi)存、內(nèi)存映射、信號量、信號、Socket) | 直接讀寫進程數(shù)據(jù)段(eg.全局變量)進行通信 | 共享內(nèi)存、消息隊列 |
四、線程實現(xiàn)
1. 線程創(chuàng)建和結(jié)束
- 一般情況下,main函數(shù)所在的線程我們稱之為主線程(main線程),其余創(chuàng)建的線程稱之為子線程。 程序中默認只有一個線程,調(diào)用pthread_create()函數(shù)產(chǎn)生新的線程。
??????// ?創(chuàng)建線程?
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);- 功能:創(chuàng)建一個子線程- 參數(shù):- thread:傳出參數(shù),線程創(chuàng)建成功后,子線程的線程ID被寫到該變量中。- attr : 設(shè)置線程的屬性,一般使用默認值,NULL- start_routine : 函數(shù)指針,這個函數(shù)是子線程需要處理的邏輯代碼- arg : 給第三個參數(shù)使用,傳參- 返回值:成功:0失敗:返回錯誤號。這個錯誤號和之前errno不太一樣。獲取錯誤號的信息: char * strerror(int errnum);
- ?獲得線程id :pthread_self
pthread_t pthread_self(void);
- ?等待線程結(jié)束:pthread_join,主線程調(diào)?,等待子線程退出并回收其資源,類似于進程中wait/waitpid回收僵尸進程,調(diào)用 pthread_join的線程會被阻塞
int pthread_join(pthread_t thread, void **retval);- 功能:和一個已經(jīng)終止的線程進行連接回收子線程的資源- 特點:這個函數(shù)是阻塞函數(shù),調(diào)用一次只能回收一個子線程一般在主線程中使用- 參數(shù):- thread:需要回收的子線程的ID- retval: 接收子線程退出時的返回值- 返回值:0 : 成功非0 : 失敗,返回的錯誤號
- 結(jié)束線程:?子線程執(zhí)行,用于結(jié)束當前線程并通過retval傳遞返回值,該返回值可通過pthread_join獲得
void pthread_exit(void *retval);功能:終止一個線程,在哪個線程中調(diào)用,就表示終止哪個線程參數(shù):retval:需要傳遞一個指針,作為一個返回值,可以在pthread_join()中獲取到。
- 分離線程:主線程、子線程均可調(diào)?。主線程中pthread_detach(tid),子線程中 pthread_detach(pthread_self()),調(diào)?后和主線程分離,子線程結(jié)束時自己立即回收資源
int pthread_detach(pthread_t thread);- 功能:分離一個線程。被分離的線程在終止的時候,會自動釋放資源返回給系統(tǒng)。1. 不能多次分離,會產(chǎn)生不可預(yù)料的行為。2. 不能去連接一個已經(jīng)分離的線程,會報錯。- 參數(shù):需要分離的線程的ID- 返回值:成功:0失敗:返回錯誤號
?2. 線程屬性
????????線程屬性對象類型為pthread_attr_t,結(jié)構(gòu)體定義如下:
typedef struct{int detachstate; // 線程分離的狀態(tài)int schedpolicy; // 線程調(diào)度策略struct sched_param schedparam; // 線程的調(diào)度參數(shù)int inheritsched; // 線程的繼承性int scope; //線程的作用域//以下為線程棧的設(shè)置size_t guardsize; //線程棧末尾警戒緩沖大小int stackaddr_set; // 線程的棧設(shè)置void * stackaddr;// 線程棧的位置size_t stacksize;//線程棧大小
}pthread_attr_t;
設(shè)置線程屬性相關(guān)函數(shù):int pthread_attr_init(pthread_attr_t *attr);- 初始化線程屬性變量int pthread_attr_destroy(pthread_attr_t *attr);- 釋放線程屬性的資源int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);- 獲取線程分離的狀態(tài)屬性int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);- 設(shè)置線程分離的狀態(tài)屬性