一般情況下,線程終止后,其終止狀態一直保留到其它線程調用pthread_join獲取它的狀態為止。但是線程也可以被置為detach狀態,這樣的線程一旦終止就立刻回收它占用的所有資源,而不保留終止狀態。不能對一個已經處於detach狀態的線程調用pthread_join,這樣的調用將返回EINVAL錯誤。也就是說,如果已經對一個線程調用了pthread_detach就不能再調用pthread_join了。
pthread_cancel函數
殺死(取消)線程 其作用,對應進程中 kill() 函數。
int pthread_cancel(pthread_t thread); 成功:0;失敗:錯誤號
【注意】:線程的取消並不是實時的,而有一定的延時。需要等待線程到達某個取消點(檢查點)。
類似於玩游戲存檔,必須到達指定的場所(存檔點,如:客棧、倉庫、城里等)才能存儲進度。殺死線程也不是立刻就能完成,必須要到達取消點。
取消點:是線程檢查是否被取消,並按請求進行動作的一個位置。通常是一些系統調用creat,open,pause,close,read,write..... 執行命令man 7 pthreads可以查看具備這些取消點的系統調用列表。也可參閱 APUE.12.7 取消選項小節。
可粗略認為一個系統調用(進入內核)即為一個取消點。如線程中沒有取消點,可以通過調用pthread_testcancel()函數自行設置一個取消點。
被取消的線程, 退出值定義在Linux的pthread庫中。常數PTHREAD_CANCELED的值是-1。可在頭文件pthread.h中找到它的定義:#define PTHREAD_CANCELED ((void *) -1)。因此當我們對一個已經被取消的線程使用pthread_join回收時,得到的返回值為-1。
【練習】:終止線程的三種方法。注意"取消點"的概念。 【pthrd_endof3.c】
終止線程方式
總結:終止某個線程而不終止整個進程,有三種方法:
-
從線程主函數return。這種方法對主控線程不適用,從main函數return相當於調用exit。
-
一個線程可以調用pthread_cancel終止同一進程中的另一個線程。
-
線程可以調用pthread_exit終止自己。
pthread_equal函數
比較兩個線程ID是否相等。
int pthread_equal(pthread_t t1, pthread_t t2);
有可能Linux在未來線程ID pthread_t 類型被修改為結構體實現。
控制原語對比
進程 線程
fork pthread_create
exit pthread_exit
wait pthread_join
kill pthread_cancel
getpid pthread_self 命名空間
接下來看代碼:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
void *func1(void * f1)
{
puts("我是第一個線程!我采用return的方式結束自己。");
return (void*)770880;
}
void *func2(void * f2)
{
puts("我是第二個線程!我采用pthread_exit的方式結束自己。");
pthread_exit((void*)1314);
}
void *func3(void * f3)
{
puts("我是第三個線程!我采用pthread_cancel的方式結束自己。");
while (1)//可能會發生線程執行完但是主線程還沒有開始調用pthread_cancel函數。
pthread_testcancel();//主動設置取消點
return (void*)520;
}
int main(void)
{
pthread_t pth[3];
void *i;
pthread_create((pth + 0), NULL, func1, NULL);
pthread_join(pth[0], (void**)&i);
printf("線程一的退出狀態:i = %d.\n", (int)i);
pthread_create((pth + 1), NULL, func2, NULL);
pthread_join(pth[1], (void**)&i);
printf("線程二的退出狀態:i = %d.\n", (int)i);
pthread_create((pth + 2), NULL, func3, NULL);
pthread_cancel(pth[2]);//殺死
pthread_join(pth[2], (void**)&i);
printf("線程三的退出狀態:i = %d.\n", (int)i);
return 0;
}
結果:
很簡單,就這樣吧。
