1、函数pthread_join
1 /************************************************************************* 2 > File Name: pthread_join1.c 3 > Summary: pthread_join函数的基本用法 4 > Author: xuelisheng 5 > Created Time: 2018年12月13日 6 ************************************************************************/ 7 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <string.h> 11 #include <unistd.h> 12 #include <errno.h> 13 #include <pthread.h> 14 15 struct thrd 16 { 17 int var; 18 char str[256]; 19 }; 20 21 void *tfn(void *arg) 22 { 23 struct thrd *tval; 24 tval = malloc(sizeof(tval)); 25 26 tval->var = 100; 27 strcpy(tval->str, "hello xls"); 28 return (void *)tval; 29 } 30 31 int main() 32 { 33 pthread_t tid; 34 struct thrd *retval; 35 int ret = pthread_create(&tid, NULL, tfn, NULL); 36 if(ret != 0) 37 { 38 printf("create thread fail\n"); 39 } 40 /* 41 函数pthread_join用来等待一个线程的结束,线程间同步的操作。头文件 : #include <pthread.h> 42 函数定义: int pthread_join(pthread_t thread, void **retval); 43 描述 :pthread_join()函数,以阻塞的方式等待thread指定的线程结束。当函数返回时,被等待线程的资源被收回。如果线程已经结束,那么该函数会立即返回。并且thread指定的线程必须是joinable的。 44 参数 :thread: 线程标识符,即线程ID,标识唯一线程。retval: 用户定义的指针,用来存储被等待线程的返回值。 45 返回值 : 0代表成功。 失败,返回的则是错误号。 46 */ 47 ret = pthread_join(tid, (void **)&retval); 48 printf("child thread exit and return values var = %d, str = %s\n", retval->var, retval->str); 49 pthread_exit(NULL); 50 return 0; 51 }
运行结果:
child thread exit and return values var = 100, str = hello xls
2、函数pthread_cancel
1 /************************************************************************* 2 > File Name: pthread_cancel1.c 3 > Summary: 终止线程的函数 pthread_cancel() 4 > Author: xuelisheng 5 > Created Time: 2018年12月13日 6 ************************************************************************/ 7 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <string.h> 11 #include <unistd.h> 12 #include <errno.h> 13 #include <pthread.h> 14 15 void *tfn(void *arg) 16 { 17 while(1) 18 { 19 printf("thread :pid = %d, tid = %lu\n",getpid(), pthread_self()); 20 sleep(1); 21 } 22 return NULL; 23 } 24 25 int main() 26 { 27 pthread_t tid; 28 int ret = pthread_create(&tid, NULL, tfn, NULL); 29 if(ret != 0) 30 { 31 printf("pthread_create fail\n"); 32 exit(1); 33 } 34 printf("main: pid = %d, tid = %lu\n",getpid(), pthread_self()); 35 36 sleep(5); 37 38 /* 39 #include<pthread.h> 40 int pthread_cancel(pthread_t thread) 41 发送终止信号给thread线程,如果成功则返回0,否则为非0值。发送成功并不意味着thread会终止。 42 若是在整个程序退出时,要终止各个线程,应该在成功发送 CANCEL 指令后,使用 pthread_join 函数,等待指定的线程已经完全退出以后,再继续执行;否则,很容易产生 “段错误”。 43 */ 44 ret = pthread_cancel(tid); // 终止线程tid 45 if(ret != 0) 46 { 47 printf("pthread_cancel fail\n"); 48 exit(1); 49 } 50 51 while(1); 52 53 54 return 0; 55 }
运行结果:
thread :pid = 20038, tid = 139963255736064 main: pid = 20038, tid = 139963264071424 thread :pid = 20038, tid = 139963255736064 thread :pid = 20038, tid = 139963255736064 thread :pid = 20038, tid = 139963255736064 thread :pid = 20038, tid = 139963255736064 (循环等待)
3、3种终止线程的方式:exit()、pthread_exit()、pthread_cancel
情形1:
1 /************************************************************************* 2 > File Name: pthread_cancel2.c 3 > Summary: 终止线程的3种方式:exit、pthread_exit()、 pthread_cancel() 4 > Author: xuelisheng 5 > Created Time: 2018年12月13日 6 ************************************************************************/ 7 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <string.h> 11 #include <unistd.h> 12 #include <errno.h> 13 #include <pthread.h> 14 15 void *tfn1(void *arg) 16 { 17 printf("thread 1 returning\n"); 18 return (void *)111; // 线程函数中,这里的return (void *)111相当于 exit(111) 19 } 20 21 void *tfn2(void *arg) 22 { 23 printf("thread 2 exiting\n"); 24 pthread_exit((void *)222); 25 } 26 27 void *tfn3(void *arg) 28 { 29 while(1) 30 { 31 printf("thread 3: I'm going to die in 3 seconds ...\n"); 32 sleep(1); 33 /*pthread_testcanel(); // 自己添加取消点*/ 34 } 35 return (void *)666; 36 } 37 int main() 38 { 39 pthread_t tid; 40 void *tret = NULL; 41 42 pthread_create(&tid, NULL, tfn1, NULL); 43 pthread_join(tid, &tret); 44 printf("thread 1 exit code = %d\n\n", (int)tret); 45 46 pthread_create(&tid, NULL, tfn2, NULL); 47 pthread_join(tid, &tret); 48 printf("thread 2 exit code = %d\n\n", (int)tret); 49 50 pthread_create(&tid, NULL, tfn3, NULL); 51 sleep(3); // 主线程休眠3秒 52 pthread_cancel(tid); 53 pthread_join(tid, &tret); // 主线程要回收子线程3,但是子线程3之前已经被cancel,tret所以返回值-1(表示失败) 54 printf("thread 3 exit code = %d\n\n", (int)tret); 55 56 return 0; 57 }
运行结果:
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
情形2:当pthread_cancel要终止的线程没有陷入内核的操作
1 /************************************************************************* 2 > File Name: pthread_cancel3.c 3 > Summary: 终止线程的3种方式:exit、pthread_exit()、 pthread_cancel() 当pthread_cancel要终止的线程没有陷入内核的操作 4 > Author: xuelisheng 5 > Created Time: 2018年12月13日 6 ************************************************************************/ 7 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <string.h> 11 #include <unistd.h> 12 #include <errno.h> 13 #include <pthread.h> 14 15 void *tfn1(void *arg) 16 { 17 printf("thread 1 returning\n"); 18 return (void *)111; // 线程函数中,这里的return (void *)111相当于 exit(111) 19 } 20 21 void *tfn2(void *arg) 22 { 23 printf("thread 2 exiting\n"); 24 pthread_exit((void *)222); 25 } 26 27 void *tfn3(void *arg) 28 { 29 while(1) // 终止的线程中没有陷入内核的操作(例如系统调用等) 30 { 31 //printf("thread 3: I'm going to die in 3 seconds ...\n"); 32 //sleep(1); 33 /*pthread_testcanel(); // 自己添加取消点*/ 34 } 35 return (void *)666; 36 } 37 int main() 38 { 39 pthread_t tid; 40 void *tret = NULL; 41 42 pthread_create(&tid, NULL, tfn1, NULL); 43 pthread_join(tid, &tret); 44 printf("thread 1 exit code = %d\n\n", (int)tret); 45 46 pthread_create(&tid, NULL, tfn2, NULL); 47 pthread_join(tid, &tret); 48 printf("thread 2 exit code = %d\n\n", (int)tret); 49 50 pthread_create(&tid, NULL, tfn3, NULL); 51 sleep(3); // 主线程休眠3秒 52 pthread_cancel(tid); 53 pthread_join(tid, &tret); // 主线程要回收子线程3,但是子线程3之前已经被cancel,tret所以返回值-1(表示失败) 54 printf("thread 3 exit code = %d\n\n", (int)tret); 55 56 return 0; 57 }
运行结果:
thread 1 returning thread 1 exit code = 111 thread 2 exiting thread 2 exit code = 222 (光标在此while循环...)
情形3:解决当pthread_cancel要终止的线程没有陷入内核的操作---创建线程取消点
1 /************************************************************************* 2 > File Name: pthread_cancel4.c 3 > Summary: 终止线程的3种方式:exit、pthread_exit()、 pthread_cancel() 解决当pthread_cancel要终止的线程没有陷入内核的操作 4 > Author: xuelisheng 5 > Created Time: 2018年12月13日 6 ************************************************************************/ 7 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <string.h> 11 #include <unistd.h> 12 #include <errno.h> 13 #include <pthread.h> 14 15 void *tfn1(void *arg) 16 { 17 printf("thread 1 returning\n"); 18 return (void *)111; // 线程函数中,这里的return (void *)111相当于 exit(111) 19 } 20 21 void *tfn2(void *arg) 22 { 23 printf("thread 2 exiting\n"); 24 pthread_exit((void *)222); 25 } 26 27 void *tfn3(void *arg) 28 { 29 while(1) // 终止的线程中没有陷入内核的操作(例如系统调用等),可以添加函数pthread_testcanel() 30 { 31 //printf("thread 3: I'm going to die in 3 seconds ...\n"); 32 //sleep(1); 33 pthread_testcancel(); // 自己添加取消点 34 } 35 return (void *)666; 36 } 37 int main() 38 { 39 pthread_t tid; 40 void *tret = NULL; 41 42 pthread_create(&tid, NULL, tfn1, NULL); 43 pthread_join(tid, &tret); 44 printf("thread 1 exit code = %d\n\n", (int)tret); 45 46 pthread_create(&tid, NULL, tfn2, NULL); 47 pthread_join(tid, &tret); 48 printf("thread 2 exit code = %d\n\n", (int)tret); 49 50 pthread_create(&tid, NULL, tfn3, NULL); 51 sleep(3); // 主线程休眠3秒 52 pthread_cancel(tid); 53 pthread_join(tid, &tret); // 主线程要回收子线程3,但是子线程3之前已经被cancel,tret所以返回值-1(表示失败) 54 printf("thread 3 exit code = %d\n\n", (int)tret); 55 56 return 0; 57 }
运行结果:
thread 1 returning thread 1 exit code = 111 thread 2 exiting thread 2 exit code = 222 thread 3 exit code = -1