在Linux线程系列的第二部分(线程创建和标识)中,我们讨论了线程ID,如何比较两个线程ID以及如何创建线程。
在本文中,我们将主要关注线程的终止方式。
Linux线程系列: part 1, part 2,第3部分(本文)。
C线程示例程序
如果我们采用本系列第二部分中讨论的相同示例:
#include<stdio.h> #include<string.h> #include<pthread.h> #include<stdlib.h> #include<unistd.h> pthread_t tid[2]; void* doSomeThing(void *arg) { unsigned long i = 0; pthread_t id = pthread_self(); if(pthread_equal(id,tid[0])) { printf("\n First thread processing\n"); } else { printf("\n 第二线程处理\n"); } for(i=0; i<(0xFFFFFFFF);i++); return NULL; } int main(void) { int i = 0; int err; while(i < 2) { err = pthread_create(&(tid[i]), NULL, &doSomeThing, NULL); if (err != 0) printf("\ncan't create thread :[%s]", strerror(err)); else printf("\n Thread created successfully\n"); i++; } sleep(5); return 0; }
你有没有观察到‘sleep()’ function being used? Did you get a question about why 睡觉() is being used? Well if you did then you are at the correct place to get the answer and if you did not then also its going to be a good read ahead.
If I remove the 睡觉() function from the code above and then try to compile and run it, I see the following output :
$ ./threads Thread created successfully First thread processing Thread created successfully
But if I run it with 睡觉() enabled then I see the output as :
$ ./threads Thread created successfully First thread processing Thread created successfully 第二线程处理
所以我们看到了日志‘第二线程处理’ is missing in case we remove the 睡觉() function.
那么,为什么会这样呢?好吧,发生这种情况是因为在即将调度第二个线程之前,父线程(从中创建了两个线程)已完成其执行。这意味着运行main()函数的默认线程已完成,因此该进程终止为main()返回。
线程终止
如上所述,每个程序都以至少一个线程开始,该线程是在其中执行main()函数的线程。因此,程序中执行的每个线程的最大生存期是主线程的生存期。因此,如果我们希望主线程应该等到所有其他线程都结束,则可以使用函数pthread_join()。
#include <pthread.h> int pthread_join(pthread_t thread, void **rval_ptr);
上面的函数确保其父线程在完成之前不会终止。从父线程内部调用此函数,第一个参数是要等待的线程的线程ID,第二个参数是我们要父线程等待的线程的返回值。如果我们对返回值不感兴趣,则可以将此指针设置为NULL。
如果我们进行更广泛的分类,则可以看到线程可以通过三种方式终止:
- 如果线程从其启动例程返回。
- 如果被其他线程取消。这里使用的函数是pthread_cancel()。
- 如果从内部调用pthread_exit()函数。
这里的重点将放在pthread_exit()上。其原型如下:
#include <pthread.h> void pthread_exit(void *rval_ptr);
因此,我们看到此函数仅接受一个参数,这是调用此函数的线程的返回值。此返回值由正在等待该线程终止的父线程访问。由pthread_exit()函数终止的线程的返回值可在上面刚刚说明的pthread_join的第二个参数中访问。
C线程终止示例
让我们举一个使用上面讨论的功能的例子:
#include<stdio.h> #include<string.h> #include<pthread.h> #include<stdlib.h> #include<unistd.h> pthread_t tid[2]; int ret1,ret2; void* doSomeThing(void *arg) { unsigned long i = 0; pthread_t id = pthread_self(); for(i=0; i<(0xFFFFFFFF);i++); if(pthread_equal(id,tid[0])) { printf("\n First thread processing done\n"); ret1 = 100; pthread_exit(&ret1); } else { printf("\n 第二线程处理 done\n"); ret2 = 200; pthread_exit(&ret2); } return NULL; } int main(void) { int i = 0; int err; int *ptr[2]; while(i < 2) { err = pthread_create(&(tid[i]), NULL, &doSomeThing, NULL); if (err != 0) printf("\ncan't create thread :[%s]", strerror(err)); else printf("\n Thread created successfully\n"); i++; } pthread_join(tid [0],(void **)&(ptr[0])); pthread_join(tid [1],(void **)&(ptr[1])); printf("\n return value from first thread is [%d]\n", *ptr[0]); printf("\n return value from second thread is [%d]\n", *ptr[1]); return 0; }
在上面的代码中:
- 我们使用pthread_create()创建了两个线程
- 两个线程的启动函数相同,即doSomeThing()
- 线程使用带有返回值的pthread_exit()函数从start函数退出。
- 创建线程之后,在主函数中,调用pthread_join()函数以等待两个线程完成。
- 两个线程完成后,它们的返回值将由pthread_join()调用中的第二个参数访问。
上面代码的输出为:
$ ./threads Thread created successfully Thread created successfully First thread processing done 第二线程处理 done return value from first thread is [100] return value from second thread is [200]
因此,我们看到两个线程都完全执行,并且在主函数中访问了它们的返回值。
如果您喜欢这篇文章,您可能还会喜欢..
![]() |
![]() |
![]() |
![]() |
很棒的文章系列,确实帮助我以简洁的方式理解了线程。