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