pthread_join函数

来源:互联网 发布:淘宝分期付款怎么扣钱 编辑:程序博客网 时间:2024/04/19 16:39

这个函数没有什么好说的。其实就两个参数,第一个是线程变量,第二个是线程返回值。其函数原型为:

int pthread_join(pthread_t thread,void** result);

不过查阅许多网上资料,依旧没有使用result这个形参的。一般的使用为pthread_join(thread,NULL);于是自己在想那个NULL能做啥米用。于是写下下面的代码:

view plaincopy to clipboardprint?
  1. #include <stdio.h>  
  2. #include <pthread.h>  
  3. int count =0;  
  4. // 初始化mutex变量。  
  5. pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;  
  6. void * print_count(int);  
  7. int main()  
  8. {  
  9.   const int num = 10;  
  10.   pthread_t threads[num];  
  11.   int i=0;  
  12.   for(i=0; i< num; i++){  
  13. //第一个参数是pthread_t变量,第二个是pthread_t变量的属性  
  14. //第三个是pthread_t需要执行的函数,其函数原型为  
  15. // void* (*startfun)(void*)  
  16. // 所以传入的是一个返回void*的函数(这里当然可以转换)  
  17. // 并且接受的是void*的参数,所以需要把i转换为void *  
  18.       pthread_create(&threads[i],NULL,print_count,(void*)i);  
  19.   }  
  20.   void* result = NULL;  
  21.   for(i=0; i < num; i++){  
  22. // 这里就是同步得到结果。打印的是线程执行的状态,0为成功。非0失败  
  23.       printf("end %d;\n",pthread_join(threads[i],&result));  
  24.       if(result == NULL){  
  25.         printf("NULL\n");  
  26.       }  
  27.       else{  
  28. // 这里打印的是pthread_t执行完print_count后返回的结果。  
  29.         printf("%x\n",result);  
  30.       }  
  31.   }  
  32.   return 0;  
  33. }  
  34. //这里返回的类型是void*,因为pthread_create中的函数指针为void*  
  35. //这里的参数int i,可有可无,如果没有pthread_create中就使用NULL作为参数。  
  36. void * print_count(int i){  
  37. // 设置mutex锁  
  38.   pthread_mutex_lock(&mutex);  
  39.   printf("thread: %d---> count %d\n",i,count);  
  40.   count++;  
  41.   sleep(2);  
  42.   printf("thread: %d---> count %d\n",i,count);  
  43. // 释放锁  
  44.   pthread_mutex_unlock(&mutex);  
  45. //这里是返回值, void * result就可以被赋值了..否则为result = NULL  
  46.   return (void*)count;  
  47. }  
#include <stdio.h> #include <pthread.h> int count =0; // 初始化mutex变量。 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; void * print_count(int); int main() { const int num = 10; pthread_t threads[num]; int i=0; for(i=0; i< num; i++){ //第一个参数是pthread_t变量,第二个是pthread_t变量的属性 //第三个是pthread_t需要执行的函数,其函数原型为 // void* (*startfun)(void*) // 所以传入的是一个返回void*的函数(这里当然可以转换) // 并且接受的是void*的参数,所以需要把i转换为void * pthread_create(&threads[i],NULL,print_count,(void*)i); } void* result = NULL; for(i=0; i < num; i++){ // 这里就是同步得到结果。打印的是线程执行的状态,0为成功。非0失败 printf("end %d;\n",pthread_join(threads[i],&result)); if(result == NULL){ printf("NULL\n"); } else{ // 这里打印的是pthread_t执行完print_count后返回的结果。 printf("%x\n",result); } } return 0; } //这里返回的类型是void*,因为pthread_create中的函数指针为void* //这里的参数int i,可有可无,如果没有pthread_create中就使用NULL作为参数。 void * print_count(int i){ // 设置mutex锁 pthread_mutex_lock(&mutex); printf("thread: %d---> count %d\n",i,count); count++; sleep(2); printf("thread: %d---> count %d\n",i,count); // 释放锁 pthread_mutex_unlock(&mutex); //这里是返回值, void * result就可以被赋值了..否则为result = NULL return (void*)count; }

另外值得注意的是pthread_join()中第二个参数不要乱传。如果非NULL,可能造成segment failure.

另外这里如果使用c++进行编译可能会有void* (*)(int)不能转换为void*(*)(void*)的问题。这是因为c++编译器要求太严格了。只好改动函数签名为void * print_count(void *);之后再进行转换。现在终于知道为啥这么多人都喜欢在linux下使用c了。

Linux下多线程(pthread)编程实例


Linux系统下的多线程遵循POSIX线程接口,称为 pthread。编写Linux下的多线程程序,需要使用头文件pthread.h,连接时需要使用库libpthread.a。顺便说一下,Linux 下pthread的实现是通过系统调用clone()来实现的。clone()是 Linux所特有的系统调用,它的使用方式类似fork,关于clone()的详细情况,有兴趣的读者可以去查看有关文档说明。下面我们展示一个最简单的 多线程程序 pthread_create.c。


一个重要的线程创建函数原型:
#include <pthread.h>
int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict attr, void *(*start_rtn)(void),void *restrict arg);

    返回值:若是成功建立线程返回0,否则返回错误的编号
形式参数:
pthread_t *restrict tidp 要创建的线程的线程id指针
const pthread_attr_t *restrict attr 创建线程时的线程属性
void* (start_rtn)(void) 返回值是void类型的指针函数
void *restrict arg   start_rtn的行参

例程1:                               
功能:创建一个简单的线程
程序名称:pthread_create.c         
/********************************************************************************************
**    Name:pthread_create.c
**    Used to study the multithread programming in Linux OS
**    Author:zeickey
**    Date:2006/9/16       
**    Copyright (c) 2006,All Rights Reserved!
*********************************************************************************************/

#include <stdio.h>
#include <pthread.h>

void *myThread1(void)
{
int i;
for (i=0; i<100; i++)
{
printf("This is the 1st pthread,created by zieckey.\n");
sleep(1);//Let this thread to sleep 1 second,and then continue to run
}
}

void *myThread2(void)
{
int i;
for (i=0; i<100; i++)
{
printf("This is the 2st pthread,created by zieckey.\n");
sleep(1);
}
}

int main()
{
int i=0, ret=0;
pthread_t id1,id2;

ret = pthread_create(&id2, NULL, (void*)myThread1, NULL);
if (ret)
{
printf("Create pthread error!\n");
return 1;
}

ret = pthread_create(&id2, NULL, (void*)myThread2, NULL);
if (ret)
{
printf("Create pthread error!\n");
return 1;
}

pthread_join(id1, NULL);
pthread_join(id2, NULL);

return 0;
}


我们编译此程序:
# gcc pthread_create.c -lpthread

因为pthread的库不是linux系统的库,所以在进行编译的时候要加上-lpthread,否则编译不过,会出现下面错误
thread_test.c: 在函数 ‘create’ 中:
thread_test.c:7: 警告: 在有返回值的函数中,程序流程到达函数尾
/tmp/ccOBJmuD.o: In function `main':thread_test.c:(.text+0x4f):对‘pthread_create’未定义的引用
collect2: ld 返回 1

  运行,我们得到如下结果:
# ./a.out
This is the 1st pthread,created by zieckey.
This is the 2st pthread,created by zieckey.
This is the 1st pthread,created by zieckey.
This is the 2st pthread,created by zieckey.
This is the 2st pthread,created by zieckey.
This is the 1st pthread,created by zieckey.
....

两个线程交替执行。
此例子介绍了创建线程的方法。
下面例子介绍向线程传递参数。


例程2:
功能:向新的线程传递整形值
程序名称:pthread_int.c
/********************************************************************************************
**    Name:pthread_int.c
**    Used to study the multithread programming in Linux OS
**    Pass a parameter to the thread.
**    Author:zeickey
**    Date:2006/9/16       
**    Copyright (c) 2006,All Rights Reserved!
*********************************************************************************************/

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void *create(void *arg)
{
int *num;
num=(int *)arg;
printf("create parameter is %d \n",*num);
return (void *)0;
}
int main(int argc ,char *argv[])
{
pthread_t tidp;
int error;

int test=4;
int *attr=&test;

error=pthread_create(&tidp,NULL,create,(void *)attr);

    if(error)
{
printf("pthread_create is created is not created ... \n");
return -1;
}
sleep(1);
printf("pthread_create is created ...\n");
return 0;       
}


编译方法:

gcc -lpthread pthread_int.c -Wall


执行结果:

create parameter is 4
pthread_create is created is  created ...


例程总结:
可以看出来,我们在main函数中传递的整行指针,传递到我们新建的线程函数中。
在上面的例子可以看出来我们向新的线程传入了另一个线程的int数据,线程之间还可以传递字符串或是更复杂的数据结构。

例程3:
程序功能:向新建的线程传递字符串
程序名称:pthread_string.c
/********************************************************************************************
**    Name:pthread_string.c
**    Used to study the multithread programming in Linux OS
**    Pass a ‘char*‘ parameter to the thread.
**    Author:zeickey
**    Date:2006/9/16       
**    Copyright (c) 2006,All Rights Reserved!
*********************************************************************************************/
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

void *create(void *arg)
{
char *name;
name=(char *)arg;
printf("The parameter passed from main function is %s  \n",name);
return (void *)0;
}

int main(int argc, char *argv[])
{
char *a="zieckey";
int error;
pthread_t tidp;

    error=pthread_create(&tidp, NULL, create, (void *)a);

    if(error!=0)
{
printf("pthread is not created.\n");
return -1;
}
sleep(1);
printf("pthread is created... \n");
return 0;
}  

  编译方法:

gcc -Wall pthread_string.c -lpthread


执行结果:
The parameter passed from main function is zieckey 
pthread is created...


例程总结:
可以看出来main函数中的字符串传入了新建的线程中。

例程4:
程序功能:向新建的线程传递字符串
程序名称:pthread_struct.c
/********************************************************************************************
**    Name:pthread_struct.c
**    Used to study the multithread programming in Linux OS
**    Pass a ‘char*‘ parameter to the thread.
**    Author:zeickey
**    Date:2006/9/16       
**    Copyright (c) 2006,All Rights Reserved!
*********************************************************************************************/
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>

struct menber
{
int a;
char *s;
};

void *create(void *arg)
{
struct menber *temp;
temp=(struct menber *)arg;
printf("menber->a = %d  \n",temp->a);
printf("menber->s = %s  \n",temp->s);
return (void *)0;
}

int main(int argc,char *argv[])
{
pthread_t tidp;
int error;
struct menber *b;
b=(struct menber *)malloc( sizeof(struct menber) );
b->a = 4;
b->s = "zieckey";

    error = pthread_create(&tidp, NULL, create, (void *)b);

    if( error )
{
printf("phread is not created...\n");
return -1;
}
sleep(1);
printf("pthread is created...\n");
return 0;
}

  编译方法:

gcc -Wall pthread_struct.c -lpthread


执行结果:
menber->a = 4 
menber->s = zieckey 
pthread is created...

    例程总结:
可以看出来main函数中的一个结构体传入了新建的线程中。
线程包含了标识进程内执行环境必须的信息。他集成了进程中的所有信息都是对线程进行共享的,包括文本程序、程序的全局内存和堆内存、栈以及文件描述符。

例程5:
程序目的:验证新建立的线程可以共享进程中的数据
程序名称:pthread_share.c

/********************************************************************************************
**    Name:pthread_share_data.c
**    Used to study the multithread programming in Linux OS
**    Pass a ‘char*‘ parameter to the thread.
**    Author:zeickey
**    Date:2006/9/16       
**    Copyright (c) 2006,All Rights Reserved!
*********************************************************************************************/
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

static int a=4;
void *create(void *arg)
{
printf("new pthread ... \n");
printf("a=%d  \n",a);
return (void *)0;
}

int main(int argc,char *argv[])
{
pthread_t tidp;
int error;

a=5;

    error=pthread_create(&tidp, NULL, create, NULL);

    if(error!=0)
{
printf("new thread is not create ... \n");
return -1;
}

sleep(1);

printf("new thread is created ... \n");
return 0;
}

编译方法:

gcc -Wall pthread_share_data.c -lpthread


执行结果:
new pthread ...
a=5 
new thread is created ...


例程总结:
可以看出来,我们在主线程更改了我们的全局变量a的值的时候,我们新建立的线程则打印出来了改变的值,可以看出可以访问线程所在进程中的数据信息。

         2、线程的终止

    如果进程中任何一个线程中调用exit,_Exit,或者是_exit,那么整个进程就会终止,
与此类似,如果信号的默认的动作是终止进程,那么,把该信号发送到线程会终止进程。
线程的正常退出的方式:
(1) 线程只是从启动例程中返回,返回值是线程中的退出码
(2) 线程可以被另一个进程进行终止
(3) 线程自己调用pthread_exit函数
两个重要的函数原型:

#include <pthread.h>
void pthread_exit(void *rval_ptr);
/*rval_ptr 线程退出返回的指针*/

int pthread_join(pthread_t thread,void **rval_ptr);
/*成功结束进程为0,否则为错误编码*/


例程6
程序目的:线程正常退出,接受线程退出的返回码
程序名称:pthread_exit.c

/********************************************************************************************
**    Name:pthread_exit.c
**    Used to study the multithread programming in Linux OS
**    A example showing a thread to exit and with a return code.
**    Author:zeickey
**    Date:2006/9/16        
**    Copyright (c) 2006,All Rights Reserved!
*********************************************************************************************/

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void *create(void *arg)
{
printf("new thread is created ... \n");
return (void *)8;
}

int main(int argc,char *argv[])
{
pthread_t tid;
int error;
void *temp;

    error = pthread_create(&tid, NULL, create, NULL);

    if( error )
{
printf("thread is not created ... \n");
return -1;
}
error = pthread_join(tid, &temp);

    if( error )
{
printf("thread is not exit ... \n");
return -2;
}

printf("thread is exit code %d \n", (int )temp);
return 0;
}

  编译方法:

gcc -Wall pthread_exit.c -lpthread


执行结果:
new thread is created ...
thread is exit code 8

    例程总结:
可以看出来,线程退出可以返回线程的int数值。线程退出不仅仅可以返回线程的int数值,还可以返回一个复杂的数据结构。

    例程7
程序目的:线程结束返回一个复杂的数据结构
程序名称:pthread_return_struct.c
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

struct menber
{
int a;
char *b;
}temp={8,"zieckey"};
void *create(void *arg)
{
printf("new thread ... \n");
return (void *)&temp;
}

int main(int argc,char *argv[])
{
int error;
pthread_t tid;
struct menber *c;

    error = pthread_create(&tid, NULL, create, NULL);

if( error )
{
printf("new thread is not created ... \n");
return -1;
}
printf("main ... \n");

    error = pthread_join(tid,(void *)&c);

    if( error )
{
printf("new thread is not exit ... \n");
return -2;
}
printf("c->a = %d  \n",c->a);
printf("c->b = %s  \n",c->b);
sleep(1);
return 0;
}


编译方法:

gcc -Wall pthread_return_struct.c -lpthread


执行结果:

main ...
new thread ...
c->a = 8
c->b = zieckey


例程总结:
一定要记得返回的数据结构要是在这个数据要返回的结构没有释放的时候应用,
如果数据结构已经发生变化,那返回的就不会是我们所需要的,而是脏数据
3、线程标识

    函数原型:

#include <pthread.h>
pthread_t pthread_self(void);

pid_t getpid(void);
getpid()用来取得目前进程的进程识别码,函数说明

    例程8
程序目的:实现在新建立的线程中打印该线程的id和进程id
程序名称:pthread_id.c

/********************************************************************************************
**    Name:pthread_id.c
**    Used to study the multithread programming in Linux OS.
**    Showing how to get the thread's tid and the process's pid.
**    Author:zeickey
**    Date:2006/9/16       
**    Copyright (c) 2006,All Rights Reserved!
*********************************************************************************************/
#include <stdio.h>
#include <pthread.h>
#include <unistd.h> /*getpid()*/

void *create(void *arg)
{
printf("New thread .... \n");
printf("This thread's id is %u  \n", (unsigned int)pthread_self());
printf("The process pid is %d  \n",getpid());
return (void *)0;
}

int main(int argc,char *argv[])
{
pthread_t tid;
int error;

    printf("Main thread is starting ... \n");

    error = pthread_create(&tid, NULL, create, NULL);

    if(error)
{
printf("thread is not created ... \n");
return -1;
}
printf("The main process's pid is %d  \n",getpid());
sleep(1);
return 0;
}


编译方法:

  
gcc -Wall -lpthread pthread_id.c

    执行结果:

Main thread is starting ...
The main process's pid is 3307 
New thread ....
This thread's id is 3086347152 
The process pid is 3307

0 0
原创粉丝点击