<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>
"); //-->

博客專(zhuān)欄

EEPW首頁(yè) > 博客 > 嵌入式Linux:線(xiàn)程的創(chuàng )建、終止、回收、取消和分離

嵌入式Linux:線(xiàn)程的創(chuàng )建、終止、回收、取消和分離

發(fā)布人:美男子玩編程 時(shí)間:2025-01-21 來(lái)源:工程師 發(fā)布文章

線(xiàn)程的創(chuàng )建、終止、取消、回收和分離操作是多線(xiàn)程編程的核心。

在多線(xiàn)程編程中,需要妥善管理線(xiàn)程的生命周期,以避免資源泄漏、競爭條件或僵尸線(xiàn)程等問(wèn)題。

1

創(chuàng )建線(xiàn)程

在 Linux 中,默認情況下,一個(gè)進(jìn)程啟動(dòng)時(shí)是單線(xiàn)程運行的,這個(gè)線(xiàn)程被稱(chēng)為 主線(xiàn)程。

然而,現代計算任務(wù)通常需要并行處理,主線(xiàn)程可以通過(guò) pthread_create() 函數創(chuàng )建額外的線(xiàn)程來(lái)并行執行任務(wù)。

這些額外的線(xiàn)程與主線(xiàn)程共享進(jìn)程的資源(如內存空間、文件描述符等),但它們有獨立的執行路徑。

pthread_create() 函數的定義如下:

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,                   void *(*start_routine) (void *), void *arg);

函數參數:

  • thread:這是一個(gè) pthread_t 類(lèi)型的指針,指向存儲線(xiàn)程 ID 的變量。pthread_t 是用于唯一標識線(xiàn)程的類(lèi)型,當創(chuàng )建線(xiàn)程成功時(shí),該變量會(huì )被賦值為新線(xiàn)程的 ID,在后續的線(xiàn)程管理中使用。

  • attr:這是一個(gè)指向 pthread_attr_t 類(lèi)型的指針,用于設置線(xiàn)程的屬性。如果設置為 NULL,則使用線(xiàn)程的默認屬性。這些屬性包括線(xiàn)程是否分離(detached)、棧大小等。如果需要設置特定的屬性,可以使用 pthread_attr_init() 和相關(guān)的屬性函數。

  • start_routine:這是線(xiàn)程執行函數的指針。新線(xiàn)程創(chuàng )建后,會(huì )從這個(gè)函數開(kāi)始執行。該函數必須符合以下原型:

void* (*start_routine)(void *arg);

它接收一個(gè) void* 類(lèi)型的參數(arg),并返回一個(gè) void* 類(lèi)型的返回值。

  • arg:這是傳遞給 start_routine 函數的參數??梢允侨我忸?lèi)型的指針。如果不需要傳遞參數,可以設置為 NULL。如果需要傳遞多個(gè)參數,可以使用結構體將它們打包后通過(guò)該指針傳入。

返回值:

  • 成功時(shí)返回 0。

  • 失敗時(shí)返回錯誤號,表示失敗的原因。例如,EAGAIN 表示系統資源不足無(wú)法創(chuàng )建新線(xiàn)程,EINVAL 表示傳入的屬性無(wú)效。

創(chuàng )建線(xiàn)程的關(guān)鍵點(diǎn):

  • 線(xiàn)程 ID: 每個(gè)線(xiàn)程都有唯一的 ID,用于區分線(xiàn)程。創(chuàng )建線(xiàn)程時(shí),pthread_create() 會(huì )將新線(xiàn)程的 ID 存儲在 pthread_t 類(lèi)型的變量中,便于后續操作。

  • 線(xiàn)程屬性: 默認情況下,線(xiàn)程使用系統的默認屬性。如果需要更改線(xiàn)程的屬性,比如將其設置為 分離線(xiàn)程 或指定線(xiàn)程的棧大小,可以通過(guò) pthread_attr_t 來(lái)設置。

  • 啟動(dòng)函數和參數: 新線(xiàn)程會(huì )從 start_routine 函數開(kāi)始執行,并傳入 arg 參數??梢酝ㄟ^(guò)將多個(gè)參數封裝在結構體中,一并傳遞給該函數。

當一個(gè)新線(xiàn)程被創(chuàng )建后,它立即加入系統的 線(xiàn)程調度隊列,并在合適的時(shí)機獲取 CPU 執行時(shí)間。

由于調度是由操作系統控制的,所以無(wú)法預料新創(chuàng )建的線(xiàn)程和主線(xiàn)程誰(shuí)會(huì )先執行。

如果程序對線(xiàn)程的執行順序有嚴格要求,可以使用同步機制(如 互斥鎖 或 信號量)來(lái)控制線(xiàn)程間的執行順序。

下面是一個(gè)創(chuàng )建線(xiàn)程并傳遞參數的簡(jiǎn)單示例:

void* thread_function(void* arg) {    int* num = (int*)arg;    printf("New thread running with argument: %dn", *num);    return NULL;}
int main() {    pthread_t thread;    int arg = 42;
    // 創(chuàng  )建線(xiàn)程,傳遞參數 arg    if (pthread_create(&thread, NULL, thread_function, &arg) != 0) {        perror("pthread_create failed");        return 1;    }
    // 等待新線(xiàn)程執行完畢    pthread_join(thread, NULL);
    printf("Main thread finishedn");    return 0;}

解釋?zhuān)?/p>

  • 線(xiàn)程函數 thread_function() 接收一個(gè) void* 類(lèi)型的參數,并將其強制轉換為 int* 類(lèi)型,打印傳入的值。

  • 主線(xiàn)程 調用 pthread_create() 創(chuàng )建了一個(gè)新線(xiàn)程,并將 arg 作為參數傳遞給新線(xiàn)程的函數 thread_function()。

  • 創(chuàng )建線(xiàn)程后,主線(xiàn)程調用 pthread_join() 等待新線(xiàn)程完成執行。如果不使用 pthread_join(),主線(xiàn)程不會(huì )等待新線(xiàn)程結束,這可能導致程序提前退出。

2

終止線(xiàn)程

在 Linux 中,終止線(xiàn)程可以通過(guò)多種方式完成,不同的方式影響線(xiàn)程的退出行為和進(jìn)程的狀態(tài)管理。

我們詳細說(shuō)明幾種終止線(xiàn)程的常用方法。

  • return: 當線(xiàn)程的 start 函數執行 return 時(shí),線(xiàn)程正常終止,并返回指定的值,返回值可以通過(guò) pthread_join() 獲取。

  • pthread_exit(): 線(xiàn)程可以通過(guò)顯式調用 pthread_exit() 來(lái)終止自身,pthread_exit() 允許線(xiàn)程在任何位置退出,返回的值也可以通過(guò) pthread_join() 獲取。

  • pthread_cancel(): 通過(guò) pthread_cancel() 可以請求取消一個(gè)線(xiàn)程,線(xiàn)程需要響應取消請求才能終止。

  • exit() 和 _exit(): 當進(jìn)程中的任意線(xiàn)程調用 exit()、_exit() 或 _Exit() 時(shí),整個(gè)進(jìn)程,包括所有線(xiàn)程,都會(huì )被終止。

2.1、通過(guò) return 語(yǔ)句退出線(xiàn)程

線(xiàn)程的 start 函數(即傳遞給 pthread_create() 的函數)在執行完畢時(shí),可以直接使用 return 語(yǔ)句返回。這種方式會(huì )使線(xiàn)程正常退出,并將返回值作為線(xiàn)程的退出碼。

這與調用 pthread_exit() 類(lèi)似。

void* thread_function(void* arg) {    // 執行一些任務(wù)    int result = 42;    return (void*)result; // 通過(guò) return 語(yǔ)句退出線(xiàn)程}

在上面的代碼中,線(xiàn)程執行完 thread_function() 后,通過(guò) return 返回 result,并且這個(gè)返回值可以通過(guò) pthread_join() 函數在主線(xiàn)程中獲取。

2.2、通過(guò) pthread_exit() 退出線(xiàn)程

pthread_exit() 是專(zhuān)門(mén)用于退出線(xiàn)程的函數,它允許線(xiàn)程在任何位置顯式退出,而不是依賴(lài)于 return。

調用 pthread_exit() 后,線(xiàn)程的控制流會(huì )立即結束,不再執行后續代碼。

pthread_exit() 函數原型:

void pthread_exit(void *retval);

參數 retval: retval 是一個(gè) void* 類(lèi)型的指針,指定線(xiàn)程的返回值,也就是線(xiàn)程的退出碼。這個(gè)值可以被其他線(xiàn)程通過(guò) pthread_join() 獲取。

示例如下:

void* thread_function(void* arg) {    int* retval = (int*)arg;    printf("Thread exiting with value: %dn", *retval);    pthread_exit(retval); // 顯式退出線(xiàn)程并返回值}
int main() {    pthread_t thread;    int arg = 42;    int* retval;
    pthread_create(&thread, NULL, thread_function, &arg);    pthread_join(thread, (void**)&retval); // 獲取線(xiàn)程的退出碼
    printf("Thread returned: %dn", *retval);    return 0;}

解釋?zhuān)?/p>

  • 在該示例中,pthread_exit() 顯式終止了線(xiàn)程,并返回參數 arg 的值。

  • 主線(xiàn)程通過(guò) pthread_join() 獲取了子線(xiàn)程的退出碼。

2.3、通過(guò) exit()、_exit() 或 _Exit() 終止整個(gè)進(jìn)程

exit()、_exit() 和 _Exit() 不是用于終止單個(gè)線(xiàn)程的,而是用于終止整個(gè)進(jìn)程。

由于線(xiàn)程共享同一個(gè)進(jìn)程資源,如果任意一個(gè)線(xiàn)程調用這些函數,整個(gè)進(jìn)程(包括所有線(xiàn)程)都會(huì )終止。

  • exit(): 正常終止進(jìn)程,執行清理函數、關(guān)閉文件描述符等。

  • _exit() 和 _Exit(): 立即終止進(jìn)程,不執行清理工作。

以下示例中,thread_function() 中調用了 exit(),導致整個(gè)進(jìn)程被終止,主線(xiàn)程也不會(huì )繼續執行。

void* thread_function(void* arg) {    printf("Thread running...n");    exit(0); // 調用 exit(),導致整個(gè)進(jìn)程終止    return NULL;}
int main() {    pthread_t thread;
    pthread_create(&thread, NULL, thread_function, NULL);    pthread_join(thread, NULL);
    // 如果沒(méi)有被 exit() 終止,主線(xiàn)程會(huì )繼續執行這行代碼    printf("Main thread finishedn");
    return 0;}

3

回收線(xiàn)程

在多線(xiàn)程編程中,當線(xiàn)程結束后,其占用的資源不會(huì )立即被系統釋放,除非顯式回收這些資源,否則這些線(xiàn)程會(huì )變成 僵尸線(xiàn)程。

在 Linux 中,回收線(xiàn)程的操作與進(jìn)程的回收類(lèi)似。

正如進(jìn)程中的父進(jìn)程可以使用 wait() 來(lái)回收子進(jìn)程的資源,線(xiàn)程中也需要通過(guò) pthread_join() 來(lái)回收線(xiàn)程資源并獲取線(xiàn)程的退出狀態(tài)。

pthread_join() 是用于 等待指定線(xiàn)程終止并回收其資源 的函數,它會(huì )阻塞調用線(xiàn)程直到目標線(xiàn)程終止。

如果線(xiàn)程已經(jīng)終止,pthread_join() 將立即返回。

通過(guò)這個(gè)函數,主線(xiàn)程或其他線(xiàn)程可以獲取目標線(xiàn)程的退出狀態(tài),并清理其占用的資源,避免產(chǎn)生僵尸線(xiàn)程。

pthread_join() 的函數原型:

int pthread_join(pthread_t thread, void **retval);

函數參數說(shuō)明:

  • thread: 這是目標線(xiàn)程的線(xiàn)程 ID,pthread_join() 將等待這個(gè)線(xiàn)程終止。

  • retval: 這是一個(gè)指向 void* 類(lèi)型的指針,指向保存線(xiàn)程返回值的內存地址。如果目標線(xiàn)程通過(guò) pthread_exit() 或 return 語(yǔ)句返回了某個(gè)值,這個(gè)值將被存儲在 *retval 指向的內存中。如果 retval 為 NULL,則表示不關(guān)心目標線(xiàn)程的返回值。

返回值:

  • 成功時(shí)返回 0。

  • 如果調用失敗,pthread_join() 將返回一個(gè)錯誤碼。例如,ESRCH 表示指定的線(xiàn)程不存在,EINVAL 表示線(xiàn)程不可被 pthread_join() 回收,或者調用線(xiàn)程嘗試等待自身終止。

以下例子中,線(xiàn)程執行完 thread_function() 后通過(guò) pthread_exit() 返回 result。

主線(xiàn)程調用 pthread_join() 等待線(xiàn)程結束,并成功獲取到了線(xiàn)程的返回值。

void* thread_function(void* arg) {    int result = 100;    printf("Thread running...n");    pthread_exit((void*)&result); // 顯式返回一個(gè)結果}
int main() {    pthread_t thread;    int* thread_result;
    // 創(chuàng  )建線(xiàn)程    pthread_create(&thread, NULL, thread_function, NULL);
    // 回收線(xiàn)程并獲取返回值    pthread_join(thread, (void**)&thread_result);
    printf("Thread returned: %dn", *thread_result);    return 0;}

3.1、pthread_join() 的使用場(chǎng)景與注意事項

pthread_join() 是 阻塞函數,它會(huì )一直等待指定線(xiàn)程結束。如果目標線(xiàn)程需要執行大量計算或處理,調用 pthread_join() 的線(xiàn)程將一直處于等待狀態(tài),直到目標線(xiàn)程終止。

如果線(xiàn)程已經(jīng)結束,pthread_join() 將立即返回。

以下示例中,主線(xiàn)程在調用 pthread_join() 時(shí)會(huì )等待 5 秒,直到 worker_function() 執行完畢為止。

void* worker_function(void* arg) {    sleep(5);  // 模擬一些長(cháng)時(shí)間運行的操作    return NULL;}
int main() {    pthread_t thread;
    pthread_create(&thread, NULL, worker_function, NULL);
    printf("Waiting for thread to finish...n");    pthread_join(thread, NULL); // 阻塞等待線(xiàn)程結束
    printf("Thread finished.n");    return 0;}

在進(jìn)程中,如果父進(jìn)程不回收子進(jìn)程,則子進(jìn)程會(huì )變?yōu)?僵尸進(jìn)程,占用系統資源。

同樣的,如果一個(gè)線(xiàn)程終止后,沒(méi)有被其他線(xiàn)程調用 pthread_join() 來(lái)回收,其內存和其他資源也不會(huì )被立即釋放,這就導致了 僵尸線(xiàn)程 的問(wèn)題。

僵尸線(xiàn)程不僅浪費資源,而且如果僵尸線(xiàn)程累積過(guò)多,可能會(huì )導致應用程序無(wú)法創(chuàng )建新的線(xiàn)程。

3.2、pthread_join() 與進(jìn)程回收的區別

雖然 pthread_join() 與進(jìn)程中的 waitpid() 類(lèi)似,都是用于等待子線(xiàn)程(或子進(jìn)程)結束并獲取其退出狀態(tài),但二者之間有一些顯著(zhù)的區別:

1、線(xiàn)程關(guān)系是對等的。

在多線(xiàn)程程序中,任何線(xiàn)程都可以調用 pthread_join() 來(lái)等待另一個(gè)線(xiàn)程的結束。即使是非創(chuàng )建該線(xiàn)程的線(xiàn)程,也可以調用 pthread_join() 來(lái)等待它的終止。線(xiàn)程之間沒(méi)有父子層級關(guān)系。

舉例來(lái)說(shuō),如果線(xiàn)程 A 創(chuàng )建了線(xiàn)程 B,線(xiàn)程 B 創(chuàng )建了線(xiàn)程 C,那么線(xiàn)程 A 可以等待線(xiàn)程 C 的結束,而不需要依賴(lài)線(xiàn)程 B。

這與進(jìn)程的父子層級結構不同,父進(jìn)程是唯一可以調用 wait() 或 waitpid() 來(lái)等待子進(jìn)程終止的進(jìn)程。

2、pthread_join() 不支持非阻塞等待。

pthread_join() 是阻塞調用,不支持類(lèi)似waitpid() 中的非阻塞模式(通過(guò)傳入 WNOHANG 標志實(shí)現)。

這意味著(zhù)線(xiàn)程調用 pthread_join() 后必須等待目標線(xiàn)程終止,不能做其他操作。如果需要更復雜的線(xiàn)程同步,通常需要引入其他機制,如 信號量、條件變量 等。

4

取消線(xiàn)程

通常情況下,線(xiàn)程會(huì )自行決定何時(shí)結束,比如通過(guò)調用 pthread_exit() 函數或者在其啟動(dòng)函數中執行 return 語(yǔ)句。

但有些場(chǎng)景下,主線(xiàn)程或其他線(xiàn)程可能需要 強制終止 某個(gè)正在運行的線(xiàn)程,這時(shí)就可以通過(guò) 取消請求 來(lái)實(shí)現。

通過(guò)調用 pthread_cancel(),可以向目標線(xiàn)程發(fā)送一個(gè)取消請求,要求它終止。

pthread_cancel() 函數原型如下:

int pthread_cancel(pthread_t thread);

參數說(shuō)明:

  • thread: 需要取消的目標線(xiàn)程的線(xiàn)程 ID。

返回值:

  • 成功時(shí)返回 0。

  • 如果調用失敗,返回錯誤碼,例如:ESRCH: 指定的線(xiàn)程不存在。

4.1、線(xiàn)程取消的響應機制

目標線(xiàn)程對取消請求的響應方式可以由其自身決定。每個(gè)線(xiàn)程都有一個(gè) 取消狀態(tài) 和 取消類(lèi)型 來(lái)控制它對取消請求的響應:

4.1.1、取消狀態(tài)

取消狀態(tài)決定了線(xiàn)程是否允許響應取消請求,線(xiàn)程可以通過(guò)調用 pthread_setcancelstate() 來(lái)修改其取消狀態(tài)。

  • PTHREAD_CANCEL_ENABLE: 表示線(xiàn)程 允許 響應取消請求(這是默認狀態(tài))。

  • PTHREAD_CANCEL_DISABLE: 表示線(xiàn)程 不允許 響應取消請求。即使收到了取消請求,線(xiàn)程仍會(huì )繼續運行,直到其取消狀態(tài)被重新設置為可取消。

pthread_setcancelstate() 函數原型:

int pthread_setcancelstate(int state, int *oldstate);

參數:

  • state: 可以是 PTHREAD_CANCEL_ENABLE 或 PTHREAD_CANCEL_DISABLE,分別表示開(kāi)啟或禁用取消請求的響應。

  • oldstate: 如果不為 NULL,將保存原先的取消狀態(tài)。

示例如下:

pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); // 禁止取消請求pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);  // 允許取消請求

4.1.2、取消類(lèi)型

取消類(lèi)型決定了線(xiàn)程 何時(shí) 響應取消請求。

可以通過(guò)調用 pthread_setcanceltype() 來(lái)設置線(xiàn)程的取消類(lèi)型:

  • PTHREAD_CANCEL_DEFERRED: 線(xiàn)程將在 某些特定的取消點(diǎn) 響應取消請求(例如調用 pthread_testcancel(),或進(jìn)行 I/O 操作時(shí))。這是默認的取消類(lèi)型。

  • PTHREAD_CANCEL_ASYNCHRONOUS: 線(xiàn)程在 收到取消請求的瞬間 就立即響應,可能導致線(xiàn)程在任意位置被取消。

pthread_setcanceltype() 函數原型:

int pthread_setcanceltype(int type, int *oldtype);

參數:

  • type: 可以是 PTHREAD_CANCEL_DEFERRED 或 PTHREAD_CANCEL_ASYNCHRONOUS,分別表示延遲響應取消或立即響應取消。

  • oldtype: 如果不為 NULL,將保存原先的取消類(lèi)型。

示例:

pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); // 設置為立即響應取消
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);      // 設置為延遲響應取消

4.2、取消點(diǎn)與線(xiàn)程清理

當線(xiàn)程的取消類(lèi)型設置為 PTHREAD_CANCEL_DEFERRED 時(shí),線(xiàn)程只有在到達某些 取消點(diǎn) 時(shí)才會(huì )響應取消請求。

取消點(diǎn)通常是一些耗時(shí)操作或系統調用,比如:

  • pthread_testcancel(): 顯式設置取消點(diǎn)。

  • 其他一些常見(jiàn)的系統調用,比如 I/O 操作、sleep()、select() 等,都是隱式取消點(diǎn)。


系統中還有許多函數可以作為取消點(diǎn),這里不再逐一列舉。您可以通過(guò)查看 man 手冊獲取更多信息,使用命令 man 7 pthreads 進(jìn)行查詢(xún)。 

pthread_testcancel() 函數原型:


void pthread_testcancel(void);


這個(gè)函數可以在代碼的任意位置顯式創(chuàng )建一個(gè)取消點(diǎn)。


調用 pthread_testcancel() 后,線(xiàn)程會(huì )檢查是否有取消請求,如果有,線(xiàn)程將在此處退出。


示例如下:


while (1) {    // 執行一些任務(wù)    pthread_testcancel(); // 在循環(huán)中顯式設置取消點(diǎn),檢查是否有取消請求}


4.3、線(xiàn)程清理處理函數

在線(xiàn)程終止時(shí)(無(wú)論是正常結束還是被取消),可以使用 清理處理函數 來(lái)進(jìn)行資源清理。


清理處理函數可以確保線(xiàn)程在取消時(shí)能夠正確釋放資源,避免資源泄露。


使用 pthread_cleanup_push() 和 pthread_cleanup_pop() 來(lái)設置清理函數:

  • pthread_cleanup_push(void (*routine)(void *), void *arg):將一個(gè)清理函數 routine 壓入棧,當線(xiàn)程退出時(shí),系統將調用該函數。

  • pthread_cleanup_pop(int execute):將清理函數從棧中彈出,execute 表示是否執行該函數。


以下例子中,當線(xiàn)程收到取消請求后,它會(huì )在 pthread_testcancel() 函數處響應取消請求并退出。


在線(xiàn)程退出時(shí),cleanup_handler() 會(huì )被調用以清理資源。


void cleanup_handler(void *arg) {    printf("Cleanup: %sn", (char *)arg);}
void* thread_function(void* arg) {    pthread_cleanup_push(cleanup_handler, "Thread resources"); // 設置清理函數    while (1) {        printf("Thread running...n");        sleep(1);        pthread_testcancel(); // 檢查是否有取消請求    }    pthread_cleanup_pop(1); // 1 表示執行清理函數    return NULL;}
int main() {    pthread_t thread;    pthread_create(&thread, NULL, thread_function, NULL);
    sleep(3);  // 等待幾秒鐘    pthread_cancel(thread); // 發(fā)送取消請求    pthread_join(thread, NULL); // 等待線(xiàn)程結束    printf("Thread has been canceled.n");
    return 0;}


正確處理線(xiàn)程的取消操作對于復雜的多線(xiàn)程應用程序至關(guān)重要,特別是在執行長(cháng)時(shí)間任務(wù)時(shí),靈活管理線(xiàn)程的取消狀態(tài)和清理行為能夠有效提高系統的穩定性和可靠性。


  • pthread_cancel() 用于向目標線(xiàn)程發(fā)送取消請求,要求其終止,但目標線(xiàn)程是否終止取決于其取消狀態(tài)和取消類(lèi)型。

  • 線(xiàn)程可以通過(guò) pthread_setcancelstate() 來(lái)控制是否響應取消請求,并通過(guò) pthread_setcanceltype() 來(lái)控制何時(shí)響應。

  • 在使用 延遲取消 的情況下,線(xiàn)程只有在特定的 取消點(diǎn) 處才會(huì )檢查取消請求,可以通過(guò) pthread_testcancel() 顯式設置取消點(diǎn)。

  • 清理處理函數 確保線(xiàn)程在被取消時(shí)能夠正確釋放資源,避免資源泄露。


5

分離線(xiàn)程

默認情況下,線(xiàn)程終止后,其資源不會(huì )立即被系統回收,除非有另一個(gè)線(xiàn)程通過(guò) pthread_join() 函數顯式地等待該線(xiàn)程終止,回收其資源。


但如果某些線(xiàn)程的退出狀態(tài)和返回值對程序來(lái)說(shuō)并不重要,且不希望手動(dòng)調用 pthread_join(),可以將該線(xiàn)程設置為 分離狀態(tài)。


分離狀態(tài)的線(xiàn)程在終止時(shí),系統會(huì )自動(dòng)回收它的資源。


要將線(xiàn)程設置為分離狀態(tài),可以調用 pthread_detach() 函數。


pthread_detach() 函數原型:


int pthread_detach(pthread_t thread);


參數說(shuō)明:

  • thread: 需要分離的目標線(xiàn)程的線(xiàn)程 ID。


返回值:

  • 成功時(shí)返回 0。

  • 如果調用失敗,返回錯誤碼,例如:

    • ESRCH: 指定的線(xiàn)程不存在或已經(jīng)被回收。

    • EINVAL: 線(xiàn)程已經(jīng)處于分離狀態(tài)。


調用 pthread_detach() 后,指定的線(xiàn)程會(huì )進(jìn)入分離狀態(tài)。

處于分離狀態(tài)的線(xiàn)程在終止時(shí),系統會(huì )自動(dòng)回收其所有資源,而無(wú)需其他線(xiàn)程顯式調用 pthread_join()。

分離狀態(tài)是不可逆的,一旦線(xiàn)程被分離,就不能再通過(guò) pthread_join() 獲取該線(xiàn)程的返回狀態(tài)或等待其結束。

以下例子中,創(chuàng )建了一個(gè)新線(xiàn)程,并通過(guò) pthread_detach() 將其分離。之后,無(wú)需調用 pthread_join(),系統將在該線(xiàn)程終止時(shí)自動(dòng)回收它的資源。


pthread_t thread;pthread_create(&thread, NULL, thread_function, NULL);pthread_detach(thread); // 將該線(xiàn)程設置為分離狀態(tài)


線(xiàn)程不僅可以由其他線(xiàn)程分離,還可以通過(guò)調用 pthread_detach(pthread_self()) 來(lái) 分離自己。

這意味著(zhù)該線(xiàn)程在終止時(shí)不需要其他線(xiàn)程來(lái)回收資源,系統將自動(dòng)處理。

示例如下:


void* thread_function(void* arg) {    pthread_detach(pthread_self()); // 分離自己    // 線(xiàn)程執行的其他操作    pthread_exit(NULL);}


線(xiàn)程分離機制特別適用于以下幾種場(chǎng)景:

  • 不關(guān)心線(xiàn)程的返回值: 如果線(xiàn)程執行的任務(wù)不需要返回值,且不希望其他線(xiàn)程顯式地等待它結束。

  • 避免僵尸線(xiàn)程: 僵尸線(xiàn)程是指已經(jīng)終止但資源未被回收的線(xiàn)程,長(cháng)時(shí)間存在僵尸線(xiàn)程會(huì )消耗系統資源。將線(xiàn)程設置為分離狀態(tài),可以避免僵尸線(xiàn)程的產(chǎn)生。

  • 長(cháng)時(shí)間運行的后臺任務(wù): 如果線(xiàn)程運行時(shí)間較長(cháng)或是后臺任務(wù),而主線(xiàn)程不需要等待其結束,分離該線(xiàn)程可以簡(jiǎn)化資源管理。


線(xiàn)程分離與 pthread_join() 的比較:


線(xiàn)程分離:

  • 使用 pthread_detach() 將線(xiàn)程設置為分離狀態(tài)。

  • 系統在線(xiàn)程終止時(shí)自動(dòng)回收資源。

  • 無(wú)法通過(guò) pthread_join() 獲取線(xiàn)程的返回值或等待線(xiàn)程終止。


pthread_join():

  • 主動(dòng)調用 pthread_join() 等待指定線(xiàn)程終止并回收資源。

  • 可以獲取線(xiàn)程的返回值或終止狀態(tài)。

  • 若沒(méi)有調用 pthread_join(),線(xiàn)程終止后會(huì )成為僵尸線(xiàn)程,直到其資源被回收。


線(xiàn)程分離在簡(jiǎn)化多線(xiàn)程程序的資源管理方面非常有用,特別是對于一些無(wú)需等待或回收的線(xiàn)程,可以通過(guò)分離機制優(yōu)化程序的性能和穩定性。

最后講兩點(diǎn)注意事項:

  • 不可逆性: 一旦線(xiàn)程被設置為分離狀態(tài),就無(wú)法恢復到可被 pthread_join() 回收的狀態(tài)。如果你將某個(gè)線(xiàn)程分離,后續便無(wú)法獲取其返回值或等待它結束。

  • 線(xiàn)程同步問(wèn)題: 如果某個(gè)線(xiàn)程執行的任務(wù)需要與其他線(xiàn)程同步完成,則不應將其分離。否則,主線(xiàn)程或其他線(xiàn)程可能無(wú)法等待該線(xiàn)程結束,導致任務(wù)未完成就繼續執行。


*博客內容為網(wǎng)友個(gè)人發(fā)布,僅代表博主個(gè)人觀(guān)點(diǎn),如有侵權請聯(lián)系工作人員刪除。



關(guān)鍵詞: 嵌入式 Linux

相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>