掌握后端开发:深入理解多线程的创建与终止

发表时间: 2024-04-23 15:03

线程创建

包括头文件

#include<pthread.h>

线程创建函数pthread_create

int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict_attr,void*(*start_rtn)(void*),void *restrict arg);

返回值

  若成功则返回0,否则返回出错编号

参数

  第一个参数为指向线程标识符的指针。

  第二个参数用来设置线程属性。

  第三个参数是线程运行函数的地址。

  最后一个参数是运行函数的参数。

注意

  在编译时注意加上-lpthread参数,以调用静态链接库。因为pthread并非Linux系统的默认库。

pthread_join函数

函数简介

函数pthread_join用来等待一个线程的结束。

函数原型为:

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

参数:

  第一个参数为被等待的线程标识符

  第二个参数为一个用户定义的指针,它可以用来存储被等待线程的返回值。

注意

这个函数是一个线程阻塞的函数,调用它的函数将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源被收回。如果执行成功,将返回0,如果失败则返回一个错误号。

pthread_exit函数

函数介绍

函数使线程退出,并返回一个空指针类型的值。

一个线程的结束有两种途径:

①函数已经结束,调用它的线程也就结束了

②通过函数pthread_exit来实现

原型

void pthread_exit(void *retval)

参数

唯一的参数是函数的返回代码

pthread_join 和 pthread_exit的区别

pthread_exit(void *ptr) 函数使线程退出,并返回一个空指针类型的值。

pthread_join(pthread_t tid,void **rtval)调用此函数的进程/线程等id为tid的线程返回或被终止,并从它那里获得返回值。

线程的创建与结束

#include <stdio.h>#include <pthread.h>//线程运行函数,返回值是void*类型,也就是返回通用指针,输入通用指针。在线程函数调用pthread_exit,以便返回值被主线程接受。void* say_hello(void* args){	/*线程的运行函数,必须void*,没说的表示返回通用指针、输入通用指针*/	printf("hello from thread\n");	pthread_exit((void*)1);}int main(){	pthread_t tid;	//成功返回0;    int iRet = pthread_create(&tid, NULL, say_hello, NULL);	/*参数依次是:创建的线程id,线程参数,调用函数名,传入的函数参数*/    if (iRet){	    printf("pthread_create error: iRet=%d\n",iRet);        return iRet;    }    //调用pthread_jion函数,获得线程的饭hi之。	void *retval;	iRet=pthread_join(tid,&retval);	if (iRet){	    printf("pthread_join error: iRet=%d\n",iRet);        return iRet;    }	printf("retval=%ld\n",(long)retval);		return 0;}

编译 g++ -lpthread -o test test.cpp,这里需要连接静态库文件pthread。执行./test命令可以得到

创建线程时间传入类类的成员函数

用Hello::say_hello传入调用函数

#include <stdio.h>#include <pthread.h>class Hello{public:    static void* say_hello(void* args){	/*线程的运行函数,必须void*,没说的表示返回通用指针、输入通用指针*/	    printf("hello from thread\n");	    pthread_exit((void*)1);    }};int main(){	pthread_t tid;    int iRet = pthread_create(&tid, NULL, Hello::say_hello, NULL);	/*参数依次是:创建的线程id,线程参数,调用函数名,传入的函数参数*/    if (iRet){	    printf("pthread_create error: iRet=%d\n",iRet);	    return iRet;    }	void *retval;	iRet=pthread_join(tid,&retval);	if (iRet){	    printf("pthread_join error: iRet=%d\n",iRet);	    return iRet;    }	printf("retval=%ld\n",(long)retval);		return 0;}

向线程传递int类型参数

#include <stdio.h>#include <pthread.h>void* say_hello(void* args){	int i=*(int*)args;	printf("hello from thread,i=%d\n",i);	pthread_exit((void*)1);}int main(){	pthread_t tid;	int para=10;	//给线程调用的函数传递一个int类型的参数para,值是10    int iRet = pthread_create(&tid, NULL, say_hello, ¶);    if (iRet){	    printf("pthread_create error: iRet=%d\n",iRet);	    return iRet;    }	void *retval;	iRet=pthread_join(tid,&retval);	if (iRet){	    printf("pthread_join error: iRet=%d\n",iRet);	    return iRet;    }	printf("retval=%ld\n",(long)retval);		return 0;}

在线程调用函数时传入一个结构体

传入时直接引用结构体地址即可

#include <stdio.h>#include <pthread.h>#include <string.h>struct arg_type{	int a;	char b[100];};void* say_hello(void* args){//进行类型转换	arg_type arg_temp=*(arg_type*)args;	printf("hello from thread,arg_temp.a=%d, arg_temp.b=%s\n",arg_temp.a,arg_temp.b);	pthread_exit((void*)1);}int main(){	pthread_t tid;	arg_type arg_temp;	arg_temp.a=10;	char temp[100]="I am number one.";	strncpy(arg_temp.b,temp,sizeof(temp));    int iRet = pthread_create(&tid, NULL, say_hello, &arg_temp);    if (iRet){	    printf("pthread_create error: iRet=%d\n",iRet);	    return iRet;    }	void *retval;	iRet=pthread_join(tid,&retval);	if (iRet){	    printf("pthread_join error: iRet=%d\n",iRet);	    return iRet;    }	printf("retval=%ld\n",(long)retval);		return 0;}

获取线程ID

有两种方式可以打印线程的ID
①在线程调用函数中使用pthread_self函数来获得线程ID
②在创建函数生成的ID。

//第一种void *function(void *arg){	printf("thread id in pthread = %lu\n",pthread_self());}
//第二种int main(){	int i = 10;	pthread_t thread;	int iRet = pthread_create(&thread,NULL,&function,&i);	if(Ret){}	printf("pthread id in process = %lu\n",thread);}