1 主线程
当C程序运行时,首先运行main函数。在线程代码中,这个特殊的执行流被称为“初始线程”或“主线程”。
初始线程的特殊性在于main函数返回阶段保留了传统UNIX进程行为,即进程结束时不会等待其他线程结束。
从main函数返回将导致进程终止,也将使进程内所有的线程终止。可以在main函数中调用pthread_exit,这样进程就必须等到所有线程结束后才能终止。
2 线程管理函数
头文件 |
#include <pthread.h> |
函数原型 |
int pthread_equal(pthread_t tid1, pthread_t tid2); |
参数 |
tid1:线程标识1 tid2:线程标识2 |
返回 |
若相等则返回非0值,否则返回0 |
功能 |
对两个线程ID进行比较 |
头文件 |
include <pthread.h> |
函数原型 |
pthread_t pthread_self(void); |
参数 |
void |
返回 |
返回调用线程的线程ID |
功能 |
获得自身线程ID |
头文件 |
include <pthread.h> |
函数原型 |
int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void), void *restrict arg); |
参数 |
tidp:获取新创建线程的线程ID attr:线程属性 start_rtn:新创建的线程从start_rtn函数的地址开始运行 arg:start_rtn的指针参数 |
返回 |
若成功则返回0,否则返回错误编号 |
功能 |
创建线程 |
线程创建时并不能保证哪个线程会先运行:是新创建的线程还是调用线程。新创建的线程可以访问进程的地址空间,并且继承调用线程的浮点环境和信号屏蔽字,但是该线程的未决信号集被清除。
头文件 |
include <pthread.h> |
函数原型 |
void pthread_exit(void *rval_ptr); |
参数 |
rval_ptr:保存线程退出后返回的值 |
返回 |
void |
功能 |
线程终止 |
rval_ptr是无类型指针,进程中的其他线程可以通过调用pthread_join函数访问该指针。
头文件 |
include <pthread.h> |
函数原型 |
int pthread_join(pthread_t thread, void **rval_ptr); |
参数 |
thread:指定的线程ID rval_ptr:获取线程退出时的返回值 |
返回 |
若成功返回0,否则返回错误编码 |
功能 |
等待一个线程的结束 |
调用pthread_join后,调用线程将一直阻塞,直到指定的线程调用pthread_exit、从启动例程中返回或者被取消。
可以通过调用pthread_join自动把线程置于分离状态,这样资源就可以恢复。如果线程已经处于分离状态,pthread_join调用就会失败,返回EINVAL。
头文件 |
include <pthread.h> |
函数原型 |
int pthread_cancel(pthread_t tid); |
参数 |
tid:线程ID |
返回 |
若成功返回0,否则返回错误编码 |
功能 |
请求取消同一进程中的其他线程。注意:pthread_cancel并不等待线程终止 |
线程可以安排它退出时需要调用的函数,这样的函数称为线程清理处理程序。线程可以建立多个清理处理程序。处理程序记录在栈中,也就是说它们的执行顺序与它们注册时的顺序相反。
头文件 |
include <pthread.h> |
函数原型 |
void pthread_cleanup_push(void (*rtn)(void *), void *arg); void pthread_cleanup_pop(int execute); |
参数 |
rtn:线程清理函数 arg:参数 execute:表示执行到pthread_cleanup_pop时是否在弹出清理函数的同时执行该函数,若execute为0,清理函数将不被执行;若为非0,则执行。 |
返回 |
void |
功能 |
线程注册清理函数。Pthread_cleanup_push和pthread_cleanup_pop可以实现为宏,所以在使用时需要配对出现。 |
头文件 |
include <pthread.h> |
函数原型 |
int pthread_detach(pthread_t tid); |
参数 |
tid:线程ID |
返回 |
若成功返回0,否则返回错误编号 |
功能 |
使线程进入分离状态。分离一个正在运行的线程不会对线程带来任何影响,仅仅是通知系统当该线程结束时,其所属资源可以被回收。 |
在默认情况下,线程的终止状态会保存到对该线程调用pthread_join,如果线程已经处于分离状态,线程的底层存储资源可以在线程终止时立即被收回。当线程被分离时,并不能用pthread_join函数等待它的终止状态。对分离状态的线程进行pthread_join的调用会产生失败,返回EINVAL.
3 线程的生命周期
状态 |
含义 |
就绪 |
线程能够运行,但在等待可用的处理器。 |
运行 |
线程正在运行。在多处理器系统中,可能有多个线程处于运行状态。 |
阻塞 |
线程由于等待处理器外的其他条件无法运行,如条件变量的改变、加锁互斥量或I/O操作结束。 |
终止 |
线程从起始函数中返回,或调用pthread_exit,或者被取消,终止自己并完成所有资源清理工作。 |
4 一个进程内的多线程
4.1 线程独有的内容
(1)线程ID
(2)寄存器
(3)堆栈
(4)调度属性
(5)待定和阻塞的信号集
(6)线程专用数据
(7)错误返回码
4.2 线程共享的内容
(1)进程代码段
(2)进程数据段
(3)进程打开的文件描述符
(4)进程的当前目录
(5)进程用户ID和进程组ID
(6)两个同样值的指针指向相同的数据
5 一个进程内的线程间的通信方式
(1)利用全局变量
(2)通过参数传递