在Linux中,线程的应用还是比较广泛的,同时,线程退出的返回值对线程来说,也是一种比较客观的数据传输。
本文主要是在Linux中进行测试,不涉及windows等其他OS。
1. 线程的创建
pthread_create(pthread_t *thread,const pthread_attr_t *attr,void*(*start_routine)(void*),void* arg);
首先,参数一:代表的是线程的pid地址
参数二:代表的是是否设置线程的分离属性,这里设置为NULL,不分离
参数三:代表的是线程的处理函数
参数四:线程处理函数的参数列表,这里设置为NULL,不带参数内容
(注意,这里主要是创建线程的作用)
2. 线程的等待
pthread_join(pthread_t thread, void **retval)
首先: 参数一: 代表线程pid
参数二: 代表线程的返回值 (--> 这个是本文讨论的重点参数)
3. 例子设计:
这里设计两个线程,线程一是通过一般的return返回,作为线程的返回值;线程二,则是使用线程库中的pthread_exit()函数
来进行返回参数。
首先,函数pthread_exit(void *retval)
这里的retval就是线程退出的时候返回给主线程的值,也是今天需要讨论的情况。
例子如下:
1 #include <pthread.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <errno.h>
6
7 #define PTHREAD_NUM 2
8
9 void *sendData(void *arg)
10 {
11 static int count = 2;
12
13 pthread_exit((void*)(&count));
14
15 }
16
17
18 void *recvData(void *arg)
19 {
20 static int count = 3;
21
22 return (void *)(&count);
23
24
25 }
26
27
28 int main(int argc,char *argv[])
29 {
30 pthread_t pid[PTHREAD_NUM];
31 int retPid;
32 int *ret;
33 int *dat;
34
35
36 if((retPid = pthread_create(&pid[0],NULL,sendData,NULL)) != 0)
37 {
38 perror("create pid first failed");
39 return -1;
40 }
41
42
43 if((retPid = pthread_create(&pid[1],NULL,recvData,NULL)) != 0)
44 {
45 perror("create pid second failed");
46 return -1;
47 }
48
49
50 if(pid[0] != 0)
51 {
52
53 pthread_join(pid[0],(void**)&ret);
54 printf("get thread 0 message: %d\n",*ret);
55 }
56
57
58 if(pid[1] != 0)
59 {
60 pthread_join(pid[1],(void**)&dat);
61 printf("get thread 1 message: %d\n",*dat);
62 }
63
64
65 return 0;
66 }
讲解:这里的最主要的问题就是我们需要进行强制类型的转换。
首先,对于pthread_exit这个函数,他的返回参数的类型为void *,现在我们返回的是一个“整数”,因此必须将其进行转换
1. 先转换为整形指针,count为int类型,那么&count为int*类型,同样为了保持匹配,这里本人使用显式的调用,直接写作为
&count,其实这个表明了现在变成了一个int的指针,这个时候与void*匹配的话,需要进行强制转换,也就是代码中的
(void*)(&count);
2. return这个关键字进行返回值得时候,同样也是需要进行强制类型的转换。线程函数的返回类型是void*,那么对于count这个
整形数值来说,必须进行转换为void的指针类型(即void*),因此有:(void*)((int*)&count);
3. 对于接收返回值的线程函数pthread_join来说,有两个作用。其一就是等待线程结束,其二就是获取线程结束的时候返回的数值
是什么。所以,对于它的参数类型是void**这种二级指针的,我们可以把它分解为一级指针,这样就比较容易进行理解和调用。本文
讨论的是整数,那么设置接收返回值得为一个整形指针,这样就感觉给二级指针void**降阶了。
4. 对接收返回值得参数进行强制转换,这里定义接收返回值得类型是int*,因此转化为void**,也就是(void**)&ret,因为&ret就已
经说明了现在的类型为int**,然后显式地转为void**即可
5. 另外,本文在返回整数数值的时候使用到了static这个关键字,这是因为必须确定返回值的地址是不变的。对于count变量而言,在
内存上来讲,属于在栈区开辟的变量,那么在调用结束的时候,必然是释放内存空间的,相对而言,这时候,就没办法找到count所代表
内容的地址空间。这就是为什么很多人在看到swap交换函数的时候,为什么写成swap(int,int)是没有办法进行交换的,所以,如果我
们需要修改传过来的参数的话,必须是要使用这个参数的地址,或者是一个变量本身是不变的内存地址空间,这样才可以进行修改,否则,
修改失败或者返回值是随机值。
结果:
上述的结果表明,返回的数值是我们所要求的数值,是正确的。读者可以试着返回的是一个字符串,这样就比返回是一个整数
更加简单明了。说到底,整篇文章也就是强制转换的结果。读者可以更加深入地自己去理解