一、相关API
1. 线程创建
1. 线程创建
#include <pthread.h>
int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
参数:
参数1:(创建的线程 的地址)当pthread_create成功返回时,由tidp指向的内存单元被设置为新创建线程的线程ID。
参数2:(配置为NULL时,指创建默认属性的线程)attr参数用于定制各种不同的线程属性,暂可以把它设置为NULL,以创建默认属性的线程。
参数3:(线程调用的函数)新创建的线程从start_rtn函数的地址开始运行,该函数只有一个无类型指针参数arg。
参数4:(传给“线程调用的函数”的参数)如果需要向start_rtn函数传递的参数不止一个,那么需要把这些参数放到一个结构中,
然后把这个结构的地址作为arg参数传入。
返回值:
若成功返回0,
否则返回错误编号
实验:
(1)创建线程,向线程传递1个参数,线程调用函数,该函数把传递给线程的参数打印出来。
描述:
如图,编写了以下代码;并且编译时连接了libpthread.a库;
ret = pthread_create(&t1,NULL,fun1,(void *)¶m);
参数一:&t1
参数二:NULL,表示新建的线程的属性为默认属性;
参数三:fun1,函数指针,该函数是新建的线程所要执行的函数,该函数只能有1个参数,如果想要传递多个参数则需要依赖结构体。
参数四:(void *)& param,是传递给fun1函数的实参;(注意:首先要把参数强制转换为指针类型,因为fun1函数的形参和返回值的类型都必须为 void 类型。void 类型又称空指针类型,表明指针所指数据的类型是未知的。使用此类型指针时,我们通常需要先对其进行强制类型转换,然后才能正常访问指针指向的数据。)fun1读取该参数时,先把arg转换为intx型指针(int *(arg)),再读取*(int *(arg));
程序中为什么加while(1); ?
答:程序运行时,不加”while(1);”时,主进程判断ret!=0会直接退出,fun1()还没执行完时主进程就退出了。
#include <stdio.h>
#include <pthread.h>
void *fun1(void *arg)
{
printf("%ld thread is created\n",(unsigned long)pthread_self());
printf("param = %d\n",*((int *)arg));
}
int main()
{
int ret;
int param = 100;
pthread_t t1;
int *pret = NULL;
ret = pthread_create(&t1,NULL,fun1,(void *)¶m);
if(ret == 0)
{
printf("creat t1 success\n");
}
while(1);
return 0;
}
运行结果:
(2)创建线程,向线程传递多个参数(这些参数都放在1个结构体里面),线程调用函数,该函数把传递给线程的参数打印出来。
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
struct STU1{
char name[128];
int param1;
int param2;
};
void *fun1(void *arg)
{
printf("%ld thread is created\n",(unsigned long)pthread_self());
printf("&Sparam %d\n",arg);
struct STU1 *p1;
p1 = (struct STU1 *)arg;
printf("arg->name::%s\n",p1->name);
printf("arg->param1::%d\n",p1->param1);
printf("arg->param2::%d\n",p1->param2);
}
int main()
{
int ret;
pthread_t t1;
int *pret = NULL;
struct STU1 Sparam = {"yrx0203",100,88};
struct STU1 *p;
p = (struct STU1 *)malloc(sizeof(struct STU1) );
p = &Sparam;
ret = pthread_create(&t1,NULL,fun1,(void *)p);
if(ret == 0)
{
printf("creat t1 success\n");
}
while(1);
return 0;
}
运行结果如图:
2.线程等待与退出
#include <pthread.h>
int pthread_join(pthread_t thread, void **rval_ptr);
参数1:线程的名称
参数2:如果对线程的返回值不感兴趣,可以把rval_ptr置为NULL。在这种情况下,调用pthread_join函数将等待指定的线程终止,但并不获得线程的终止状态。
如果对线程的返回值感兴趣,则把参数二设置为void型的二级指针。(这个二级指针传递给线程后,在线程退出时, int pthread_exit(void *rval_ptr);会改变这个二级指针的值)
返回值:
若成功返回0,
否则返回错误编号
调用这个函数的线程将一直阻塞,直到指定的线程调用pthread_exit从启动例程中返回或者被取消。
如果例程只是从它的启动例程返回,rval_ptr将包含返回码。
如果线程被取消,由rval_ptr指定的内存单元就置为PTHREAD_CANCELED。
可以通过调用pthread_join自动把线程置于分离状态,这样资源就可以恢复。如果线程已经处于分离状态,pthread_join调用就会失败,返回EINVAL。
#include <stdio.h>
#include <pthread.h>
void *fun1(void *arg)
{
static ret =10;
printf("%ld thread is created\n",(unsigned long)pthread_self());
printf("param = %d\n",*((int *)arg));
pthread_exit((void *)&ret);
}
int main()
{
int ret;
int param = 100;
pthread_t t1;
int *pret = NULL;
ret = pthread_create(&t1,NULL,fun1,(void *)¶m);
if(ret == 0)
{
printf("creat t1 success\n");
}
pthread_join(t1,(void **)&pret);
printf("*pret=%d\n",*pret);
while(1);
return 0;
}
运行结果: