第9章 线程编程(2)_线程创建和终止
2. 线程的创建和终止
(1)创建函数:pthread_create
|
头文件 |
#include <pthread.h> |
|
函数 |
int pthread_create(pthread_t* tidp, const pthread_attr_t* attr, void*(*start_rtn)(void*),void* arg); |
|
返回值 |
成功返回0,否则返回错误编号 |
|
参数 |
(1)tidp:线程标识符指针 (2)attr:线程属性指针 (3)start_rtn:线程运行函数的起始地址 (4)arg:传递给线程运行函数的参数 |
|
备注 |
(1)新创建线程从start_rtn函数的地址开始执行 (2)不能保证新线程和调用线程的执行顺序。 |
【编程实验】龟兔赛跑
//pthread_race.c
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//实例:龟兔赛跑
//编译选项:gcc -o bin/pthread_race src/pthread_race.c -lpthread
//定义线程函数的参数类型
typedef struct
{
char name[20]; //线程名称
int time; //休眠时间
int start; //起点
int end; //终点
}RaceArg;
//定义线程运行函数
void* th_fn(void* arg)
{
RaceArg* ra = (RaceArg*)arg;
int i = ra->start;
for(; i<=ra->end; i++){
printf("%s(%lx) run %d\n", ra->name, pthread_self(), i);
usleep(ra->time); //time为微秒
}
return (void*)(ra->end - ra->start); //返回跑过的路程.
//也可以调用pthread_exit((void*)(ra-end - ra-start));来终止线程
}
int main(void)
{
srand48(time(NULL)); //随机种子,对伪随机发生器drand48进行初始化
int err = 0;
pthread_t rabbit, turtle; //定义兔子和乌龟线程
//要传递给线程函数的参数(drand48返回值为介于0-1之间的double型随机数)
RaceArg r_a = {"rabbit", (int)(drand48() * 10* 1000 * 10), 20, 50};
RaceArg t_a = {"turtle", (int)(drand48() * 10* 1000 * 10), 10, 60};
//创建兔子线程(rabbit)
if(err = pthread_create(&rabbit, NULL, th_fn, (void*)&r_a) != 0){
perror("pthread_create error");
}
//创建乌龟线程(turtle)
if(err = pthread_create(&turtle, NULL, th_fn, (void*)&t_a) != 0){
perror("pthread_create error");
}
//等待rabbit线程结束
int* ret = NULL;
pthread_join(rabbit, (void**)&ret); //pthread_join(rabbit, NULL);不关心子线程返回值
printf("rabbit's distance is %d\n",(int)ret);
//等待turtle线程结束
pthread_join(turtle, (void**)&ret);
printf("turtle's distance is %d\n", (int)ret); //pthread_join(turtle, NULL);
printf("main thread id: %lx\n", pthread_self());
printf("main thread finished!\n");
return 0;
}
(2)线程的终止
①主动终止:线程的执行函数中调用return语句或pthread_exit()
②被动终止:线程可以被同一进程的其它线程取消(调用pthread_cancel(pthid))。
③终止相关的函数
|
头文件 |
#include <pthread.h> |
|
函数 |
int pthread_cancel(pthread_t tid); //终止tid线程,tid被动终止 int pthread_exit(void* retval); //主动终止 int pthread_join(pthread_t th, void** thread_return);//等待线程结束 |
|
返回值 |
成功返回0,否则返回错误编号 |
|
参数 |
(1)tid:要终止的线程标识符 (2)retval:pthread_exit调用者线程的返回值,可由其他函数和pthread_join来检测获取。 (3)th:pthread_join等待的子线程标识符。 (4)thread_return:用户自定义指针,用来存储被等待线程的返回值。 |
|
备注 |
(1)pthread_cancel:线程可以被同一进程的其他进程取消。 (2)由于一个进程中的多个线程共享数据段,因此通常在线程退出后,退出线程所占用的资源并不会随线程的结束而释放,所以需要调用pthread_join函数来等待线程结束,类似于wait系统调用。 |
【编程实验】线程的终止
//pthread_term.c
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
/*获取线程终止的返回值*/
//定义线程函数的参数
typedef struct
{
int data1;
int data2;
}Arg;
//定义线程函数
void* th_fn(void* arg)
{
Arg* ret = (Arg*)arg;
//return (void*)(r->data1 + r->data2);
return ret;
}
int main()
{
int err = 0;
pthread_t th;
Arg r = {20, 50};
//创建新线程
if((err = pthread_create(&th, NULL, th_fn, (void*)&r)) != 0){
perror("pthread_create error");
}
/*
//获取子线程的返回值
int* result = NULL; //因为子线程的返回值是void*,当传入pthread_join后
//result本身会被改为子线程返回的值,而不在是NULL。
//这也是传入二级指针的目的,改变result本身的值。
pthread_join(th, (void**)&result);
printf("result is %d\n", (int)result);
*/
//获取子线程的返回值
Arg* result = NULL;
pthread_join(th, (void*)&result);
printf("result is %d\n", result->data1 + result->data2);
return 0;
}

浙公网安备 33010602011771号