這篇文章主要介紹了簡單了解C語言中主線程退出對子線程的影響,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
對于程序來說,如果主進程在子進程還未結束時就已經退出,那么Linux內核會將子進程的父進程ID改為1(也就是init進程),當子進程結束后會由init進程來回收該子進程。
那如果是把進程換成線程的話,會怎么樣呢?假設主線程在子線程結束前就已經退出,子線程會發生什么?
在一些論壇上看到許多人說子線程也會跟著退出,其實這是錯誤的,原因在于他們混淆了線程退出和進程退出概念。實際的答案是主線程退出后子線程的狀態依賴于它所在的進程,如果進程沒有退出的話子線程依然正常運轉。如果進程退出了,那么它所有的線程都會退出,所以子線程也就退出了。
主線程先退出
先來看一個主線程先退出的例子:
#include <pthread.h>#include <unistd.h>#include <stdio.h>void* func(void* arg){ pthread_t main_tid = *static_cast<pthread_t*>(arg); pthread_cancel(main_tid); while (true) { //printf("child loops/n"); } return NULL;}int main(int argc, char* argv[]){ pthread_t main_tid = pthread_self(); pthread_t tid = 0; pthread_create(&tid, NULL, func, &main_tid); while (true) { printf("main loops/n"); } sleep(1); printf("main exit/n"); return 0;}
把主線程的線程號傳給子線程,在子線程中通過pthread_cancel終止主線程使其退出。運行程序,可以發現在打印了一定數量的「main loops」之后程序就掛起了,但卻沒有退出。
主線程因為被子線程終止了,所有沒有看到「main exit」的打印。子線程終止了主線程后進入了死循環while中,所以程序看起來像掛起了。如果我們讓子進程while循環中的打印語句生效再運行就可以發現程序會一直打印「child loops」字樣。
主線程被子線程終止了,但他們所依賴的進程并沒有退出,所以子線程依然正常運轉。
主線程隨進程一起退出
之前看到一些人說如果主線程先退出了,子線程也會跟著退出,其實他們混淆了線程退出和進程退出的概念。下面這個例子代表了他們的觀點:
void* func(void* arg){ while (true) { printf("child loops/n"); } return NULL;}int main(int argc, char* argv[]){ pthread_t main_tid = pthread_self(); pthread_t tid = 0; pthread_create(&tid, NULL, func, &main_tid); sleep(1); printf("main exit/n"); return 0;}
運行上面的代碼,會發現程序在打印一定數量的「child loops」和一句「main exit」之后退出,并且在退出之前的最后一句打印是「main exit」。
按照他們的邏輯,你看,因為主線程在打印完「main exit」后退出了,然后子線程也跟著退出了,所以隨后就沒有子線程的打印了。
但其實這里是混淆了進程退出和線程退出的概念了。實際的情況是主線程中的main函數執行完ruturn后彈棧,然后調用glibc庫函數exit,exit進行相關清理工作后調用_exit系統調用退出該進程。所以,這種情況實際上是因為進程運行完畢退出導致所有的線程也都跟著退出了,并非是因為主線程的退出導致子線程也退出。
Linux線程模型
實際上,posix線程和一般的進程不同,在概念上沒有主線程和子線程之分(雖然在實際實現上還是有一些區分),如果仔細觀察apue或者unp等書會發現基本看不到「主線程」或者「子線程」等詞語,在csapp中甚至都是用「對等線程」一詞來描述線程間的關系。
新聞熱點
疑難解答