首页 > 学院 > 开发设计 > 正文

77-线程创建与终止

2019-11-06 07:12:33
字体:
来源:转载
供稿:网友

在《线程初识》中,我们已经了解到了创建线程的函数 pthread_create 函数。本篇打算详细介绍一下pthread_create函数,另外还有线程终止及相关的函数。

1. 线程创建

函数原型typedef void *(*start_routine) (void *);int pthread_create(pthread_t *thread, const pthread_attr_t *attr, start_routine th_fn, void *arg);

pthread_t 类型是线程 id 的类型,它可能是个整数(大多数是这样),也可能是结构体,这取决于具体实现。thread 参数是一个传出参数,它主要用来接收被创建的线程的 id 号。在线程执行过程中调用函数pthread_self函数,可以获取到自己的线程 id 号。

pthread_attr_t 类型是用来保存线程属性的结构体,通常参数 attr 可以传 NULL,表示创建具有默认属性的线程。有关线程的属性结构体,后文会作具体讲解。

start_routine 是用来声明函数型如 void* th_fn(void* arg) 这样的函数的,它是线程过程函数。线程被创建后,一旦被调度,就会进入到函数 th_fn 中执行。

最后一个参数 arg,是线程过程函数 th_fn 的参数。

pthread_create 函数的返回值是一个错误码,返回 0 表示成功。和其它 POSIX 函数不同的是,pthread_create 函数执行错误并不会设置 errno 变量。

2. 线程终止

2.1 线程终止方式

线程的终止包括两大类,主动终止和被动终止。

主动终止 线程过程函数执行 return 正常返回,返回值是线程的退出码纯种过程函数执行 pthread_exit 函数退出,其参数是线程退出码被动终止 在其它线程中调用 pthread_cancel 函数任意线程调用 exit、_Exit 或者 _exit 导致整个进程终止

2.2 pthread_exit 函数

pthread_exit 函数原型

void pthread_exit(void *rval_ptr);

该函数的参数是线程的退出码,它是无类型的指针。通过函数 pthread_join 可以获取到这个指针的值。该函数有点类似于我们之前学习的 waitpid 函数,它可以回收线程所使用的资源。

int pthread_join(pthread_t tid, void **rval_ptr);

调用pthread_join 会阻塞当前线程,直到指定的线程 tid 返回(return)、执行 pthread_exit 或者被其它线程取消(pthread_cancel)。rval_ptr 是一个输出参数,它用来接收线程退出码(是一个 void* 类型)。

2.3 pthread_cancel 函数

int pthread_cancel(pthread_t tid);

默认情况下,该函数的效果相当于在线程 tid 中调用 pthread_exit((void*)PTHREAD_CANCEL) 函数。

3. 示例(线程主动退出)

程序代码// threadexit.c#include <unistd.h> #include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #define ERR(name,err) do{PRintf("%s:%s/n",#name,strerror(err));exit(-1);}while(0); void* th_fn1(void* arg) { puts("thread 1 returning"); return (void*)10; } void* th_fn2(void* arg) { puts("thread 2 exiting"); pthread_exit((void*)20); puts("thread 2 exited"); } int main() { pthread_t tid1, tid2; int err; void* ret; err = pthread_create(&tid1, NULL, th_fn1, NULL); if (err != 0) ERR(pthread_create1, err); err = pthread_create(&tid2, NULL, th_fn2, NULL); if (err != 0) ERR(pthread_create2, err); sleep(2); // 主线程阻塞直到线程 tid1 退出 err = pthread_join(tid1, &ret); if (err != 0) ERR(pthread_join1, err); printf("thread 1 exit code %d/n", (int)ret); // 主线程阻塞直到线程 tid2 退出 err = pthread_join(tid2, &ret); if (err != 0) ERR(pthread_join2, err); printf("thread 2 exit code %d/n", (int)ret); return 0; } 编译和运行$ gcc threadexit.c -o threadexit -lpthread$ ./threadexit运行结果

这里写图片描述 图1 线程主动终止

4. 示例(被动终止)

代码// threadcancel.c#include <unistd.h>#include <pthread.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#define ERR(name,err) do{printf("%s:%s/n",#name,strerror(err));exit(-1);}while(0);void* th_fn1(void* arg) { while(1) { puts("thread 1 running"); sleep(1); } return (void*)10;}void* th_fn2(void* arg) { while(1) { puts("thread 2 running"); sleep(1); } pthread_exit((void*)20);}int main() { pthread_t tid1, tid2; int err; void* ret; err = pthread_create(&tid1, NULL, th_fn1, NULL); if (err != 0) ERR(pthread_create1, err); err = pthread_create(&tid2, NULL, th_fn2, NULL); if (err != 0) ERR(pthread_create2, err); sleep(5); // 通知 tid1 和 tid2 退出。 pthread_cancel(tid1); pthread_cancel(tid2); err = pthread_join(tid1, &ret); // 线程退出码都是 PTHREAD_CANCELED printf("PTHREAD_CANCELED = %d/n", (int)PTHREAD_CANCELED); if (err != 0) ERR(pthread_join1, err); printf("thread 1 exit code %d/n", (int)ret); err = pthread_join(tid2, &ret); if (err != 0) ERR(pthread_join2, err); printf("thread 2 exit code %d/n", (int)ret); return 0;}编译和运行$ gcc threadcancel.c -o threadcancel -lpthread$ ./threadcancel运行结果

这里写图片描述 图2 线程被动终止

5. 总结

掌握线程创建函数掌握线程终止的几种方式
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表