(1)pthread_cancel函數
int pthread_cancel(pthread_t thread);??? 成功:0;失敗:錯誤號
作用:殺死(取消)線程,其作用對應進程中 kill() 函數。
注意:線程的取消并不是實時的,而有一定的延時。需要等待線程到達某個取消點(檢查點)。殺死線程不是立刻就能完成,必須要到達取消點。取消點:是線程檢查是否被取消,并按請求進行動作的一個位置。通常是一些系統調用creat,open,pause,close,read,write等等。執行命令man 7 pthreads可以查看具備這些取消點的系統調用列表。也可參閱 APUE.12.7 取消選項小節。
可粗略認為一個系統調用(進入內核)即為一個取消點。如線程中沒有取消點,可以通過調用pthread_testcancel( )函數自行設置一個取消點,即在子線程的執行的函數中調用該函數即可:pthread_testcancel( );? 該函數是庫函數,但執行該庫函數需要進一步使用系統調用,從而到達檢查點。只要線程到達檢查點,如果有其它線程對其調用了pthread_cancel函數,則該線程就會自動終止。
被取消的線程,退出值為常數PTHREAD_CANCELED的值是-1。可在頭文件pthread.h中找到它的定義:#define PTHREAD_CANCELED ((void *) -1)。因此當我們對一個已經被取消的線程使用pthread_join回收時,得到的返回值為-1。
//終止線程的三種方法。注意“取消點”的概念。
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>void *tfn1(void *arg) //方法1:retun
{printf("thread 1 returning\n");return (void *)111;
}void *tfn2(void *arg) //方法2:pthread_exit
{printf("thread 2 exiting\n");pthread_exit((void *)222);
}void *tfn3(void *arg) //方法三:pthread_cancel
{while (1) {printf("thread 3: I'm going to die in 3 seconds ...\n"); //取消點sleep(1); //同樣是取消點 //pthread_testcancel(); //自己添加取消點}return (void *)666;
}int main(void)
{pthread_t tid;void *tret = NULL;pthread_create(&tid, NULL, tfn1, NULL);pthread_join(tid, &tret);printf("thread 1 exit code = %d\n\n", (int)tret);pthread_create(&tid, NULL, tfn2, NULL);pthread_join(tid, &tret);printf("thread 2 exit code = %d\n\n", (int)tret);pthread_create(&tid, NULL, tfn3, NULL);sleep(3);pthread_cancel(tid);pthread_join(tid, &tret);printf("thread 3 exit code = %d\n", (int)tret);return 0;
}
[root@localhost 01_pthread_test]# ./pthrd_endof3
thread 1 returning
thread 1 exit code = 111
?
thread 2 exiting
thread 2 exit code = 222
?
thread 3: I'm going to die in 3 seconds ...
thread 3: I'm going to die in 3 seconds ...
thread 3: I'm going to die in 3 seconds ...
thread 3 exit code = -1
分析:
- 線程3執行的函數的函數體中的printf函數會調用write系統調用;sleep函數會調用pause系統調用;而pthread_testcancel也會調用系統調用,因此這三個函數都是取消點;
- 如果線程3執行的函數的函數體中的while循環體為空(即刪除上述三個函數),則該子線程將會永遠不會被殺死,而主控線程將會永遠阻塞等待回收子線程。這都是由于子線程沒有取消點的原因,因此可以自己加取消點:pthread_testcancel。
- 終止某個線程而不終止整個進程,有三種方法:從線程主函數return,這種方法對主控線程不適用,從main函數return相當于調用exit;一個線程可以調用pthread_cancel終止同一進程中的另一個線程;線程可以調用pthread_exit終止自己。
(2)pthread_equal函數
int pthread_equal(pthread_t t1, pthread_t t2);
作用:比較兩個線程ID是否相等。
返回值:相等返回非0值,不等返回0值。
由于目前的Linux系統中,線程ID類型為大于0的整數,因此可以用==直接比較是否相等;設置該函數是因為有可能Linux在未來線程ID pthread_t 類型被修改為結構體實現,因此==就無法直接判斷。