目录
[1.2 线程相关的API函数](#1.2 线程相关的API函数)
[1.2.1 线程的创建](#1.2.1 线程的创建)
[1.2.2 线程退出](#1.2.2 线程退出)
[1.2.3 线程等待函数](#1.2.3 线程等待函数)
[1.2.4 获取线程ID](#1.2.4 获取线程ID)
[1.2.5 线程取消](#1.2.5 线程取消)
[1.2.6 线程的清理函数](#1.2.6 线程的清理函数)
一、线程
1.1线程的基本概念
线程是属于进程;一个进程可以有多个线程;
线程的作用就是:解决多任务并发运行
进程和线程的区别:
1.和进程相比, 它是一种非常"节俭" 的多任务操作方式( 启动一个进程所花费的空间
远远大于启动一个线程所花费的空间( 30 倍左右) , 而且, 线程间彼此切换所需的时间也远小于进程间切换所需要的时间( >10 倍) ) 。 在 linux 系统中建立一个新的进程必须分配给它独立的地址空间, 建立众多的数据表来维护它的代码段、 堆栈段和数据段等。 而运行于同一个进程的多个线程, 它们之间使用相同的地址空间, 而且线程间彼此切换所需的时间也远小于进程间切换的时间。
2.线程间方便的通信机制。 对于不同进程,它们有独立的数据空间 数据的交互只能使
用进程通信 的方式, 这种方式费时, 而且不方便。 但是同一个进程下的线程之间共享数据空间, 所以一个线程的数据可 以直接为其他线程所有, 快捷, 方便。
线程的缺点:一个线程的非正常死亡,会导致进程退出,进而所有的线程均会死亡。
线程和进程在使用上各有优缺点:线程执行开销小, 占用的 CPU 资源少, 线程之间的切换快,但不利于资 源的管理和保护; 而进程正相反。 从可移植性来讲, 多进程的可移植性要好些。 要注意的是 由于线程共享了进 程的资源和地址空间, 因此, 任何线程对系统资源的操作都会给其他线程带来影响, 同时编写多线程程序, 最复 杂的事情是处理好各线程对共享资源的访问控制。
如何选择使用进程和线程:
1) 需要频繁创建销毁的优先用线程,因为对进程来说创建和销毁一个进程代价是很大的。
2)线程的切换速度快, 所以在需要大量计算, 切换频繁时用线程, 还有耗时的操作使用线程可高应用程序的响应;
3) 强相关的处理用线程, 弱相关的处理用进程;
4) 因为对 CPU 系统的效率使用上线程更占优, 所以可能要发展到多机分布的用进程, 多核分用线程;
5) 需要更稳定安全时, 适合选择进程; 需要速度时, 选择线程更好。
6) 如果线程和进程都各有优势和劣势, 选你喜欢的/你擅长的
1.2 线程相关的API函数
在wubantul inux操作系统上使用线程库函数需要进行调用,
gcc main -o main -lpthread
1.2.1 线程的创建
头文件:#include<pthread.h>
函数原型:
cs
int pthread_create(
pthread_t *restrict_thread, //线程号 %lu
const pthread_attr_t *restrict_attr, //NULL
void *(*start_routine)(void*), //函数指针, 传函数名即可
void *restrict arg); //传给上一个参数的参数
参数:
线程ID //unsigned long
线程属性 // NULL
线性入口函数
传递给线程入口函数的参数
返回值:
成功返回0 失败返回错误号(非0)
1.2.2 线程退出
头文件:#include<pthread.h>
函数原型:
cs
void pthread_exit(void *value_ptr);
参数:保存线程退出的状态
1.2.3 线程等待函数
头文件:#include<pthread.h>
函数原型:
cs
int pthread_join(pthread_t thread, void **value_ptr);
作用:等待指定的线程退出,该函数是一个阻塞函数,一直等到参数pthid指定的线程返回;与多进程中的wait 或 waitpid 类似
参数:
要等待的线程ID
保存线程退出的状态 一般指定NULL
返回值:成功返回0,失败返回非0
1.2.4 获取线程ID
函数原型:
cs
pthread_t pthread_self(void)
返回值:线程号,不同的线程有不同的线程号,但是线程号是相同的
1.2.5 线程取消
作用:取消一个还没有运行完的线程
函数原型:
cs
int pthread_cancel(pthread_t thread);
参数:thread: 线程号
1.2.6 线程的清理函数
作用:有时候希望线程退出时能自动的执行某些函数
函数原型:
cs
void pthread_cleanup_push(void (*routine)(void*), void *arg); 是清理注册函数
void pthread_cleanup_pop(int execute);是执行函数, 只有里面的参数 execute=1 才会执行
注意:这两个函数都是成双成对出现的,不能单独使用。
参数:
routine: 注册清理的函数的指针
arg: 传递给清理函数的参数
execute: 决定这个清理函数是否被调用
有三种情况线程清理函数会被调用:
线程还未执行 pthread_cleanup_pop 前, 被 pthread_cancel 取消
线程还未执行 pthread_cleanup_pop 前, 主动执行 pthread_exit 终止
线程执行 pthread_cleanup_pop, 且 pthread_cleanup_pop 的参数为 1
线程的清理函数中的顺序和栈一样,满足先后出。