前言:首先要明白一点的是,线程和子进程最明显的不同在于子进程在内存空间上独立于主进程的,而线程是与主进程共享内存空间的。对于初学者,除此差别外,对于线程的学习,我们可以类比子进程fork来学习。
一下是需要学习的函数:(初学者特殊特质作了解)
线程创建:pthread_create();线程号获取:pthread_self(); 线程等待:pthread_join();
线程终止:pthread_excit();
pthread_cancel();
特殊设置:pthread_setcancelstate();
pthread_setcanceltype();
线程分离状态:pthread_detach();
一、线程的创建——pthread_create();
头文件:#include<pthread.h>函数原型:int pthread_create(pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine) (void *),
void *arg);
函数功能:创建一个新的线程<把start_routine函数改造为一个线程>!
形参列表:
thread:新创建线程的线程号。通过传地址的方式返回出来!
attr:线程属性,看下面结构体! 默认:NULL
start_routine:线程函数指针!
arg:传递给start_routine函数的传参!
返回值:
成功:0
失败:负数
线程属性结构体:
typedef struct
{
int detachstate; //是否与其他线程脱离同步
int schedpolicy; //新线程的调度策略
struct sched_param schedparam; //运行优先级等
int inheritsched; //是否继承调用者线程的值
int scope; //线程竞争CPU的范围(优先级的范围)
size_t guardsize; //警戒堆栈的大小
int stackaddr_set; //堆栈地址集
void * stackaddr; //堆栈地址
size_t stacksize; //堆栈大小
} pthread_attr_t;
二、线程的线程号——pthread_self();
线程号唯一标识一个线程!
线程号获取函数: pthread_self();
函数原型:pthread_t pthread_self(void);
函数功能:获取当前线程的线程号
形参列表:无
返回值:成功:线程号
三、线程的等待——pthread_join();
函数原型:int pthread_join(pthread_t thread, void **retval);
函数功能:等待线程号为thread的线程结束,获取返回值。 释放线程空间
形参列表:
thread:线程号 <要等待的线程>
retval:结束返回值的变量空间指针!
返回值:
成功:0
失败:负数注意:retval返回值是由pthread_exit()返回的! 即pthread_join()和pthread_exit()一般结合使用!
四、线程的终止——pthread_excit()与pthread_cancel()
终止一个线程的方法有:1)return :可以终止一个线程!
2)pthread_exit(); :标准的线程终止函数!
(1)线程函数调用pthread_exit();,该线程结束!
(2)主程序调用pthread_exit(); 主程序结束。但是不释放进程空间,等到最后一个线程运行结束,
进程空间才会释放!
3)pthread_cancel(); 一个线程取消另一个线程!
pthread_exit();
函数原型:void pthread_exit(void *retval);
函数功能:结束一个线程。返回线程的结束状态
形参列表:
retval:线程的结束状态
返回值:无
pthread_cancel();(危险,慎用,了解)
函数原型:int pthread_cancel(pthread_t thread);
函数功能:取消线程号为thread的线程
形参列表:
thread:线程号
返回值:
成功:0失败:非0
五、线程的特殊设置(初学者了解)
pthread_setcancelstate();
函数原型:int pthread_setcancelstate(int state, int *oldstate);
函数功能:设置接收到cancel信号后的处理方式: 响应、忽略
形参列表:
state:设置为的处理方式
PTHREAD_CANCEL_ENABLE:响应取消信号
PTHREAD_CANCEL_DISABLE:忽略取消信号
oldstate:设置之前的处理方式
返回值:
成功:0
失败:非0
pthread_setcanceltype();
函数原型:int pthread_setcanceltype(int type, int *oldtype);
函数功能:设置线程接收到取消信号后的响应类型:立即响应,等到下一个节点响应
形参列表:
type:要设置的响应类型
PTHREAD_CANCEL_DEFERRED:等待下一个取消节点才响应
PTHREAD_CANCEL_ASYNCHRONOUS:立即响应取消信号
oldtype:设置之前的响应类型
返回值:
成功:0失败:非0
五、线程的分离态——detach()
为什么要设置成分离态进程? 因为避免僵尸线程,线程空间无法释放!
为什么分离态可以避免?因为分离态线程的存储器资源在它终止时由系统自动释放!
设置分离态的方法其实有两种:
1)调用pthread_detach()函数;
pthread_detach();函数原型:int pthread_detach(pthread_t thread);函数功能:把线程号为thread的线程分离属性设置为分离状态形参列表:thread:线程号返回值:成功:0失败:负数(不同类型错误,代码不一样)
2)属性设置法(比较麻烦)
就是在创建线程pthread_create()时,设置其第二个入口参数(*attr)
线程属性:
typedef struct{int detachstate; //是否与其他线程脱离同步int schedpolicy; //新线程的调度策略struct sched_param schedparam; //运行优先级等int inheritsched; //是否继承调用者线程的值int scope; //线程竞争CPU的范围(优先级的范围)size_t guardsize; //警戒堆栈的大小int stackaddr_set; //堆栈地址集void * stackaddr; //堆栈地址size_t stacksize; //堆栈大小} pthread_attr_t;
其中最常用的属性是detachstate属性。该属性用来决定当前线程是分离还是非分离的状态!
默认状态下,线程都是非分离状态的!
detachstate分离属性状态有:PTHREAD_CREATE_DETACHED :分离状态PTHREAD_CREATE_JOINABLE :非分离状态
具体设置过程如下:
pthread_attr_t attr; //声明结构体pthread_attr_init(&attr); //初始化结构体pthread_attr_setdetachstate(&attr, detachstate); //设置是否分离
pthread_create(&pid, pthread_attr_t* &attr, void* (*func) (void*), void* arg); //创建分离线程pthread_attr_destroy(&attr); //释放结构体