上午我說了循環建立多個線程,因爲進程與線程是如此的類似,進程咱們知道要回收,那麼線程也天然要回收啦。咱們接着看控制原語: 多線程
線程與共享 函數
線程間共享全局變量! spa
【牢記】:線程默認共享數據段、代碼段等地址空間,經常使用的是全局變量。而進程不共享全局變量,只能藉助mmap。 線程
pthread_exit函數 指針
將單個線程退出 進程
void pthread_exit(void *retval); 參數:retval表示線程退出狀態,一般傳NULL 內存
思考:使用exit將指定線程退出,能夠嗎? 【pthrd_exit.c】 string
結論:線程中,禁止使用exit函數,會致使進程內全部線程所有退出。 it
在不添加sleep控制輸出順序的狀況下。pthread_create在循環中,幾乎瞬間建立5個線程,但只有第1個線程有機會輸出(或者第2個也有,也可能沒有,取決於內核調度)若是第3個線程執行了exit,將整個進程退出了,因此所有線程退出了。 io
因此,多線程環境中,應儘可能少用,或者不使用exit函數,取而代之使用pthread_exit函數,將單個線程退出。任何線程裏exit致使進程退出,其餘線程未工做結束,主控線程退出時不能return或exit。
另注意,pthread_exit或者return返回的指針所指向的內存單元必須是全局的或者是用malloc分配的,不能在線程函數的棧上分配,由於當其它線程獲得這個返回指針時線程函數已經退出了。
總結exit、return、pthread_exit各自退出效果。
return:返回到調用者那裏去。
pthread_exit():將調用該函數的線程退出
exit: 將進程退出。
pthread_join函數
阻塞等待線程退出,獲取線程退出狀態 其做用,對應進程中 waitpid() 函數。
int pthread_join(pthread_t thread, void **retval); 成功:0;失敗:錯誤號
參數:thread:線程ID (【注意】:不是指針);retval:存儲線程結束狀態。
對比記憶:
進程中:main返回值、exit參數-->int;等待子進程結束 wait 函數參數-->int *
線程中:線程主函數返回值、pthread_exit-->void *;等待線程結束 pthread_join 函數參數-->void **
參數 retval 非空用法。
調用該函數的線程將掛起等待,直到id爲thread的線程終止。thread線程以不一樣的方法終止,經過pthread_join獲得的終止狀態是不一樣的,總結以下:
上面說的很清楚啦,因此回收線程的代碼實現也很簡單啦:
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <stdlib.h>
typedef struct {
int x;
int y;
char p[128];
}my_func;
void *func(void*arg)
{
my_func *mf = (my_func*)malloc(sizeof(my_func));
int i = (int)arg;
mf->x = i;
mf->y = i * i;
strcpy(mf->p, "my lover is dandan.");
printf("我是第%d個線程,個人線程ID是%lu\n", i + 1, pthread_self());
pthread_exit(mf);
}
int main(void)
{
pthread_t pth[5];
my_func *mf;//這裏是指針啊,是指針啊,不是一個實例啊
for (int i = 0; i != 5; i++)
{
pthread_create((pth + i), NULL, func, (void*)i);
if (!pthread_join(pth[i], (void**)&mf))
{
printf("回收線程成功!線程ID:%lu。\n", pth[i]);
printf("my_func中的x = %d, y = %d, p = %s。\n\n", mf->x, mf->y, mf->p);
}
else
printf("失敗!\n");
}
return 0;
}
主要是各類轉化要注意,還有的是:my_func *mf;//這裏是指針啊,是指針啊,不是一個實例啊 這句話很重要啊,我就說爲何個人mf輸出像是沒有通過初始化和賦值操做的。還有,不用擔憂我沒有free而形成內存泄漏,pthread_exit函數是把這些考慮好了的。還有個人pthread_exit是傳參數進去的,主要是想獲取一下線程退出的狀態。是否是和wait很相似?