一.多线程程序设计
1. 线程概述:
线程是进程中的一个实体(线程是进程的组成单元),线程是系统进行任务调度的最小单元。
一个进程至少具有一个线程,如果进程只有一个线程时,该线程就代表了当前进程,我们称
这样的线程为主线程。
一个进程中的多个线程可以并发执行。
在一个进程中启用多个线程完成不同任务实现的程序设计方法称为多线程程序设计。
******注意事项: 在多线程程序设计中一定要遵循如下原则: 主线程不能先于子线程退出。
2. 使用多线程完成多任务处理的优缺点
优点 1) 资源消耗少
2) 效率高 线程间调度时所需系统时间比较少
3) 不需要过多的数据通讯方式。因为线程间是共享进程地址空间的数据;
缺点 1) 线程间共享数据,将带来共享数据的同步和互斥问题、
3. 线程的基本操作
3.1 线程创建;
pthread_create
头文件: #include <pthread.h>
函数原型: int pthread_create(pthread_t *id,pthread_attr_t* attr,
void*(*routine)(void*),void* arg);
函数功能: 创建线程
函数参数: id : 指向线程标识符的指针变量,用于获取创建的子线程的ID
attr: 设置线程属性,NULL表明创建缺省属性的线程
routine: 指向线程函数的指针变量,用于接收线程函数的入口地址
arg : 传递给线程函数的参数
函数返回值: 成功 : 0
失败 : 返回错误码
例子:
void* add(void* arg)
{
((int*)arg)[0]
}
int a[2] = {4,7};
pthread_create(..,NULL,add,a)
2.2 获取线程ID
pthread_self
头文件: #include <pthread.h>
函数原型: pthread_t pthread_self(void);
函数功能: 创建线程自身ID
函数参数: 无
函数返回值: 返回当前线程ID
2.3 线程退出
pthread_exit
头文件: #include <pthread.h>
函数原型: void pthread_exit(void* exitcode);
函数功能: 结束调用线程,并将exitcode 作为线程函数的返回值
函数参数: exitcode: 线程函数的返回值
函数返回值: 无
注意: 由于返回的是一个指针变量,请确保返回指针同时,指针指向的内存数据不能被回收;
2.4 线程等待
pthread_join
头文件: #include <pthread.h>
函数原型: int pthread_join(pthread_t id,void** ret);
函数功能: 阻塞调用线程,直到被等待的线程结束
函数参数: id 被等待线程的标识符
ret: 用于获取被等待线程结束后返回的数据
函数返回值: 成功 0
失败 错误码
2.5 线程取消
pthread_cancel
头文件: #include <pthread.h>
函数原型: int pthread_cancel(pthread_t id);
函数功能: 向id代表的目标线程发送取消请求,请求对方退出
函数参数: id 被取消线程的标识符
函数返回值: 成功 0
失败 错误码
pthread_setcancelstate
头文件: #include <pthread.h>
函数原型: int pthread_setcancelstate(int state,int* old);
函数功能: 为调用线程设置可取消状态
函数参数: state 可取消状态状态值
PTHREAD_CANCEL_DISABLE
PTHREAD_CANCEL_EABLE (缺省值)
old 原取消状态状态值
函数返回值: 成功 0
失败 错误码
2.6 线程清理
pthread_cleanup_push / pthread_cleanup_pop
头文件: #include <pthread.h>
函数原型: void pthread_cleanup_push(void(*rtn)(void*),void* arg);
void pthread_cleanup_pop(int execute);
函数功能: 为线程设置/解除清理函数
函数参数: rtn : 清理函数,函数实现资源释放
arg: 传递给清理函数的参数
execute: 非零: 线程执行到pthread_cleanup_pop处参数非零,调用清理函数后解除
零: 线程执行到pthread_cleanup_pop处参数为零,解除清理函数
函数返回值: 无
实际使用:
1. pthread_cleanup_push 和 pthread_cleanup_pop成对使用,且调用次数严格对等;
2. 将线程函数中的代码尽可能多的包含在这两个函数之间;
3. 线程正常终止的代码放置在pthread_cleanup_pop之后
4. pthread_cleanup_pop 函数传递 0 参数;
4. 线程属性及属性设置
相关数据类型: pthread_attr_t
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;
属性设置步骤:
1. 定义 pthread_attr_t的 变量 (线程属性对象);
2. 属性初始化
pthread_attr_init
头文件: #include <pthread.h>
函数原型: int pthread_attr_init(pthread_attr_t *attr);
函数功能: 初始化线程属性对象
函数参数: attr : 待初始化的线程对象的地址
函数返回值: 成功 0
失败 错误码
3. 利用相关属性设置函数更新线程属性对象
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);
int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);
int pthread_attr_getstacksize(const pthread_attr_t *attr, size_t*stacksize);
.....
4. 利用线程属性对象创建线程
pthread_create(&threadid,&attr,rtn,&arg);
5. 回收线程属性对象
pthread_attr_destroy
头文件: #include <pthread.h>
函数原型: int pthread_attr_destroy(pthread_attr_t *attr);
函数功能: 回收线程属性对象
函数参数: attr : 待回收的线程对象的地址
函数返回值: 成功 0
失败 错误码