LinuxC系统多线程程序设计
一.多线程程序设计
1. 线程概述:
1.1 什么是线程?
线程是进程中的一个实体(组成单元),是系统进程调度的最小单元。
一个进程至少具有一个线程,如果进程仅有一个线程,该线程就代表
进程本身。把代表进程本身的线程称为主线程,一个进程中的多个线程,
共享进程地址空间,且可以并发执行。
1.2 多线程程序设计?
在一个进程中通过启动多个线程完成不同功能任务的程序设计方法,称为多线程程序设计。
*****注意:主线程代表了进程本身,主线程一旦退出则进程结束,系统回收进程资源,
所以在多线程程序设计中,一定不要让主线程先于其他线程退出。
1.3 多线程程序设计的优缺点:
1.资源消耗少. 创建线程不需要额外的系统资源,仅需要一点点线程赖以运行的栈资源。
2.效率高, 系统对线程的调度所花费的时间要远远的小于进程。
3.线程不需要众多的通讯方式。线程共享进程地址空间
不足:
线程数据是共享的,共享资源会带来资源访问的同步或互斥问题,
幸运的是: 系统提供了众多成熟的解决方法来处理同步或互斥问题,
所以多线程程序设计的优势得到了最大程度的体现。
1.4 线程的基础操作
1) 线程创建
pthread_create
函数头文件 #include <pthread.h>
函数原型: int pthread_create(pthread_t *id,const pthread_attr_t *attr,
void*(*routine)(void*),void* argp);
函数功能: 创建线程,编译时需要通过 -lpthread 链接线程库
函数参数: id: [OUT] 获取创建后的线程的ID
attr: 线程属性,NULL表示创建缺省属性的线程
routine: 线程函数的入口地址
argp: 传递给线程函数的参数
函数返回值: 成功返回0
返回错误码
2) 线程ID获取
pthread_self
函数头文件 #include <pthread.h>
函数原型: pthread_t pthread_self(void);
函数功能: 获取调用线程ID,编译时需要通过 -lpthread 链接线程库
函数参数: 无
函数返回值: 调用线程ID
该函数不会失败
3) 线程退出
pthread_exit
函数头文件 #include <pthread.h>
函数原型: void pthread_exit(void* retval);
函数功能: 线程退出,编译时需要通过 -lpthread 链接线程库
函数参数: retval: 线程退出后,返回的数据地址
函数返回值: 无
4) 线程等待
pthread_join
函数头文件 #include <pthread.h>
函数原型: int pthread_join(pthread_t id,void** retval);
函数功能: 阻塞调用线程,直到等待的线程退出,编译时需要通过 -lpthread 链接线程库
函数参数: id: 等待的目标线程的ID
retval:用于接收线程退出时返回的地址
函数返回值: 成功返回0
返回错误码
注意: 1. 线程等待不限于主线程与子线程之间,子线程也可以等待另一个子线程退出;
2. 同一个不能被等待多次
3. 不是所有线程都可以被等待(分离属性的线程是不可被等待的)
4. 线程等待的目的:
1) 需要获取指定线程的返回数据;
2) 回收等待的目标线程的资源;
3) 阻塞调用线程,
5) 线程取消
pthread_cancel
函数头文件 #include <pthread.h>
函数原型: int pthread_cancel(pthread_t id);
函数功能: 向目标线程发送退出请求,编译时需要通过 -lpthread 链接线程库
函数参数: id: 取消的目标线程的ID
函数返回值: 成功返回0
返回错误码
pthread_setcanceltype
函数头文件 #include <pthread.h>
函数原型: int pthread_setcancelstate(int state,int* oldstate);
函数功能: 设置线程退出状态,编译时需要通过 -lpthread 链接线程库
函数参数: state: 新设置的状态值,取值如下:
PTHREAD_CANCEL_ENABLE: 接受退出请求
PTHREAD_CANCEL_DISABLE: 拒绝退出请求
oldstate:[OUT] 获取原状态值
函数返回值: 成功返回0
返回错误码
6) 线程清理
pthread_cleanup_push / pthread_cleanup_pop
函数头文件 #include <pthread.h>
函数原型: void pthread_cleanup_push(void(*rtn)(void*),void* argp);
void pthread_cleanup_pop(int execute);
函数功能: pthread_cleanup_push: 为线程设置清理函数,
pthread_cleanup_pop: 取消清理函数
编译时需要通过 -lpthread 链接线程库
函数参数: rtn: 清理函数的入口地址
argp: 传递给清理函数的参数
execute:非0时,在取消清理函数之前先调用后取消
0直接取消
函数返回值: 无
注意: 1. 这两个函数要成对使用,且调用次数严格对等。
2. 在具体使用过程中,用这两个函数尽可能多的"包裹"线程函数代码,
pthread_cleanup_pop放置在线程函数的最末尾(return语句之前),
并传递0参数。
1.5 线程属性及设置
1. 线程属性
typedef struct
{
int detachstate; //线程的分离状态
int schedpolicy; //线程调度策略
struct sched_param schedparam; //线程的调度参数
int inheritsched; //线程的继承性
int scope; //线程的作用域
size_t guardsize; //线程栈尾警戒缓冲区大小
int stackaddr_set;
void * stackaddr; // 线程栈的位置
size_t stacksize; // 线程栈的大小
}pthread_attr_t;
2. 属性设置
2.1 初始化属性对象(结构体变量)
pthread_attr_init
2.2 利用属性设置相关函数设置属性对象
pthread_attr_setdetachstate
pthread_attr_setstacksize
2.3 利用设置好以后的属性对象创建线程。
2.4 回收属性对象
pthread_attr_destroy