【pthread_cancel函数:避免踩坑】
文章目錄
- pthread_cancel()函數(shù)是什么?
- 1、pthread_cancel() 函數(shù)生效,代碼演示:
- 2、pthread_cancel() 函數(shù)不生效,代碼演示
- 總結
pthread_cancel()函數(shù)是什么?
線程結束執(zhí)行的方式共有 3 種,分別是:
1.線程將指定函數(shù)體中的代碼執(zhí)行完后自行結束;
2.線程執(zhí)行過程中,遇到 pthread_exit() 函數(shù)結束執(zhí)行。
3.線程執(zhí)行過程中,被同一進程中的其它線程(包括主線程)強制終止;
- 第一種方式:很容易理解,就是函數(shù)內(nèi)所有代碼執(zhí)行完畢后,線程主動結束。
- 第二種方式:已經(jīng)在《pthread_exit()函數(shù)》一節(jié)中做了詳細的介紹。
- 第 3 種方式:本節(jié)給大家重點介紹,多線程程序中,一條線程可以借助
pthread_cancel() 函數(shù)向另一條線程發(fā)送“終止執(zhí)行”的信號(后續(xù)稱“Cancel”信號),從而令目標線程結束執(zhí)行。
pthread_cancel() 函數(shù)聲明在<pthread.h>頭文件中,語法格式如下:
int pthread_cancel(pthread_t tid); //向 tid 目標線程發(fā)送 Cancel 信號如果 pthread_cancel() 函數(shù)成功地發(fā)送了 Cancel 信號,返回數(shù)字 0;反之如果發(fā)送失敗,函數(shù)返回值為非零數(shù)。對于因“未找到目標線程”導致的信號發(fā)送失敗,函數(shù)返回 ESRCH 宏(定義在<errno.h>頭文件中,該宏的值為整數(shù) 3)。
注意,pthread_cancel() 函數(shù)的功能僅僅是向目標線程發(fā)送 Cancel 信號,至于目標線程是否處理該信號以及何時結束執(zhí)行,由目標線程決定。
對于接收 Cancel 信號后結束執(zhí)行的目標線程,等同于該線程自己執(zhí)行如下語句:
pthread_exit(PTHREAD_CANCELED);也就是說,當一個線程被強制終止執(zhí)行時,它會返回 PTHREAD_CANCELED 這個宏(定義在<pthread.h>頭文件中)。
1、pthread_cancel() 函數(shù)生效,代碼演示:
#include <stdio.h> #include <pthread.h> #include <unistd.h> // sleep() 函數(shù)//創(chuàng)建一個互斥量 pthread_mutex_t mutex;//線程執(zhí)行的函數(shù) void * thread_func1(void * arg) {printf("新建線程開始執(zhí)行.....\n");//加鎖pthread_mutex_lock(&mutex);printf("新建線程執(zhí)行中.....\n");sleep(10); //在系統(tǒng)調(diào)用sleep()時設置一個取消點(cancelpoint),線程將會從這里直接退出 //解鎖pthread_mutex_unlock(&mutex);printf("新建線程執(zhí)行完畢.....\n"); }int main() {pthread_t myThread;void * mess;int value;int res;//初始化互斥量pthread_mutex_init(&mutex, NULL);//創(chuàng)建 myThread 線程res = pthread_create(&myThread, NULL, thread_func1, NULL);if (res != 0) {printf("線程創(chuàng)建失敗\n");return 0;}sleep(1);//向 myThread 線程發(fā)送 Cancel 信號res = pthread_cancel(myThread);if (res != 0) {printf("終止 myThread 線程失敗\n");return 0;}//獲取已終止線程的返回值res = pthread_join(myThread, &mess);if (res != 0) {printf("等待線程失敗\n");return 0;}//如果線程被強制終止,其返回值為 PTHREAD_CANCELEDif (mess == PTHREAD_CANCELED) {printf("myThread 線程被強制終止\n");}else {printf("error\n");}//釋放互斥量資源pthread_mutex_destroy(&mutex);return 0; }假設程序編寫在 pthread_cancel.c 文件中,執(zhí)行過程為:
[root@localhost ~]# gcc pthread_cancel.c -o thread -lpthread
[root@localhost ~]# ./thread
新建線程開始執(zhí)行…
新建線程執(zhí)行中…
myThread 線程被強制終止
*注意:thread_func1()函數(shù)內(nèi)加了互斥鎖,但是并沒有解鎖線程就直接退出了,這就導致了死鎖。這就是我想提醒大家使用 pthread_cancel()函數(shù)時需要重點關注的地方。
2、pthread_cancel() 函數(shù)不生效,代碼演示
#include <stdio.h> #include <pthread.h> #include <unistd.h> // sleep() 函數(shù)//創(chuàng)建一個互斥量 pthread_mutex_t mutex;//線程執(zhí)行的函數(shù) void * thread_func2(void * arg) {printf("新建線程開始執(zhí)行.....\n");//加鎖pthread_mutex_lock(&mutex);printf("新建線程執(zhí)行中.....\n");//sleep(10); //函數(shù)內(nèi)沒有系統(tǒng)調(diào)用,故沒有設置一個取消點(cancelpoint),線程將不會退出而是繼續(xù)往下執(zhí)行代碼 //解鎖pthread_mutex_unlock(&mutex);printf("新建線程執(zhí)行完畢.....\n"); }int main() {pthread_t myThread;void * mess;int value;int res;//初始化互斥量pthread_mutex_init(&mutex, NULL);//創(chuàng)建 myThread 線程res = pthread_create(&myThread, NULL, thread_func2, NULL);if (res != 0) {printf("線程創(chuàng)建失敗\n");return 0;}sleep(1);//向 myThread 線程發(fā)送 Cancel 信號res = pthread_cancel(myThread);if (res != 0) {printf("終止 myThread 線程失敗\n");return 0;}//獲取已終止線程的返回值res = pthread_join(myThread, &mess);if (res != 0) {printf("等待線程失敗\n");return 0;}//如果線程被強制終止,其返回值為 PTHREAD_CANCELEDif (mess == PTHREAD_CANCELED) {printf("myThread 線程被強制終止\n");}else {printf("error\n");}//釋放互斥量資源pthread_mutex_destroy(&mutex);return 0; }假設程序編寫在 pthread_cancel.c 文件中,執(zhí)行過程為:
[root@localhost ~]# gcc pthread_cancel.c -o thread -lpthread
[root@localhost ~]# ./thread
新建線程開始執(zhí)行…
新建線程執(zhí)行中…
新建線程執(zhí)行完畢…
終止 myThread 線程失敗
*注意:thread_func2()函數(shù)沒有按照預想的方式直接退出。
總結
大家發(fā)現(xiàn)沒?
1.pthread_cancel()函數(shù)不是直接使得目標線程退出的,而是在系統(tǒng)調(diào)用中設置一個取消點(cancelpoint),當有系統(tǒng)調(diào)用函數(shù)時就會檢查是否設置了這個cancelpoint,如果設置了就立即退出線程,否則不退出。
2.sleep()函數(shù)屬于系統(tǒng)調(diào)用,當使用了sleep()時系統(tǒng)就會檢查cancelpoint,這時就會讓目標線程直接退出。但是在thread_func2()函數(shù)中沒有系統(tǒng)調(diào)用函數(shù),而是我們自己編寫的C代碼,所以不會設置這個cancelpoint,故不會退出線程。
感謝以下博主提供思路:
1.pthread_cancel()函數(shù):終止線程執(zhí)行
2.線程退出函數(shù)pthread_cancel() 采坑點
總結
以上是生活随笔為你收集整理的【pthread_cancel函数:避免踩坑】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java-php-python-ssm早
- 下一篇: 在前端如何玩转 Word 文档