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