线程之多线程函数 一线程的概念进程是操作系统分配的最小单位而线程是进程内部的执行单元是操作系统CPU调度的最小单位简单来说就是一个进程可以有多个线程。二与进程对比维度进程线程资源独立的地址空间、文件描述符等系统资源共享所属进程的地址空间和资源调度进程是资源分配的基本单位线程是 CPU 调度的基本单位开销创建 / 切换开销大需复制页表等创建 / 切换开销小共享资源仅保存少量寄存器通信需通过 IPC管道、消息队列、共享内存可直接读写共享变量通信简单但需同步健壮性进程崩溃不影响其他进程一个线程崩溃会导致整个进程退出应用场景进程适用于资源隔离要求高稳定性优先的场景如Web服务器的工作进程数据库的多进程架构线程适用于高并发计算密集型任务如Web服务器的线程池GUI程序的后台任务处理三多线程相关函数1.前置条件头文件#include pthread.h编译时必须加链接库参数gcc main.c -o main -lpthread所有pthread函数成功返回0失败返回错误码2.创建线程pthread_create作用创建一个新线程让它开始指定的函数参数结构如下int pthread_create( pthread_t *thread, // 输出存储新线程的ID const pthread_attr_t *attr, // 线程属性默认填NULL void *(*start_routine)(void *), // 线程要执行的函数指针也称入口函数 void *arg // 传递给线程函数的参数无参数填NULL );3.等待线程结束pthread_join作用阻塞等待指定线程执行完毕并回收线程资源避免内存泄漏参数结构如下int pthread_join( pthread_t thread, // 要等待的线程ID void **retval // 接收线程的返回值不接收填NULL );4.线程主动退出pthread_exit线程自己调用主动终止运行可以带返回值结构如下void pthread_exit(void *retval); // retval线程返回值ps即使主线程退出子线程也能继续执行5.获取线程自身线程idpthread_self线程获取自己的id类似于进程的getpid结构如下pthread_t pthread_self(void);线程属性相关函数6.分离线程pthread_detach将线程设置为分离态分离态下线程退出后系统自动回收其资源无需调用pthread_join结构如下int pthread_detach(pthread_t thread);7.初始化线程属性pthread_attr_init初始化线程属性对象将属性设置为默认值结构如下int pthread_attr_init(pthread_attr_t *attr);//attr需要被初始化的线程属性对象8.设置线程属性对象的分离状态pthread_attr_setdetachstate用于设置线程属性对象的分离状态结构如下int pthread_attr_setdetachstate( pthread_attr_t *attr, //设置分离状态的线程属性对象 int detachstate //用于指定线程的分离状态 //PTHREAD_CREATE_JOINABLE 表示将线程设置为结合态 //PTHREAD_CREATE_DETACHED 表示将线程设置为分离态 );9.销毁线程属性pthread_attr_destroy销毁属性对象占用的资源与初始化函数成对使用结构如下int pthread_attr_destroy(pthread_attr_t *attr);ps销毁后的属性可以重新初始化不影响已创建的线程。线程取消相关函数10.请求取消指定线程pthread_cancel向指定线程发送取消请求它只是一个请求调用成功也只是代表请求已提交不代表线程已经终止了结构如下int pthread_cancel(pthread_t thread);11.设置取消状态:pthread_setcancelstate设置调用线程自身的取消状态即是否允许响应pthread_cancel的请求,参数参数说明state新的取消状态二选一PTHREAD_CANCEL_ENABLE默认允许响应取消请求PTHREAD_CANCEL_DISABLE禁止响应取消请求请求会被暂时挂起oldstate输出参数存储修改前的旧状态传NULL表示不需要保存旧状态int pthread_setcancelstate(int state, int *oldstate);12.设置取消类型pthread_setcanceltype设置调用线程自身的取消类型仅在取消状态为PTHREAD_CANCEL_ENABLE时生效决定线程收到请求后何时终止,参数参数说明type新的取消类型二选一PTHREAD_CANCEL_DEFERRED默认延时取消线程不会立刻终止直到下一个取消点Cancellation Point才响应PTHREAD_CANCEL_ASYNCHRONOUS异步取消线程收到请求后会 “随时终止”风险极高oldtype输出参数存储修改前的旧类型传NULL表示不需要保存旧类型int pthread_setcanceltype(int type, int *oldtype);13.取消函数的示例代码//请求取消指定线程 /* 请求取消指定线程取决于线程的取消状态和取消类型 取消状态可取消和不可取消 取消类型延时取消和可被立即取消异步取消 三种情况 1. 可取消的线程延时取消 2. 可取消的线程可被立即取消 3. 不可取消的线程 */ #include stdio.h #include pthread.h #include string.h #include unistd.h #include stdlib.h //情况1可取消的线程延时取消 void *thread1(void *arg) { //设置线程1取消状态和取消类型 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL); pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL); while(1) { //结果不会每隔1秒打印一次线程1正在运行... //因为线程1收到请求取消信号线程1会在取消点进行取消 printf(线程1正在运行...\n); sleep(1); } return NULL;//注意此处返回值不可以为丢没有实际意义 } //情况2可取消的线程可被立即取消 void *thread2(void *arg) { //设置线程2取消状态和取消类型 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL); while(1) { //因为设置为了立即取消所以线程2会立即取消 //所以将sleep注释之后无法显示 printf(线程2正在运行...\n); //sleep(1); } return NULL;//注意此处返回值不可以为丢没有实际意义 } //情况3不可取消的线程 void *thread3(void *arg) { //设置线程3取消状态为不可取消 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL); while(1) { //因为设置为了不可取消所以线程3不会取消 printf(线程3正在运行...\n); sleep(1); } return NULL;//注意此处返回值不可以为丢没有实际意义 } int main(int argc,const char *argv[]) { //情况1可取消的线程延时取消 pthread_t tid1 0; int ret pthread_create(tid1,NULL,thread1,NULL); if(ret ! 0) { fprintf(stderr,创建线程1失败,错误信息%s\n,strerror(ret)); return -1; } printf(创建线程1成功,线程1ID:%ld\n,tid1); //情况2可取消的线程可被立即取消 pthread_t tid2 0; int ret2 pthread_create(tid2,NULL,thread2,NULL); if(ret2 ! 0) { fprintf(stderr,创建线程2失败,错误信息%s\n,strerror(ret2)); return -1; } printf(创建线程2成功,线程2ID:%ld\n,tid2); //情况3不可取消的线程 pthread_t tid3 0; int ret3 pthread_create(tid3,NULL,thread3,NULL); if(ret3 ! 0) { fprintf(stderr,创建线程3失败,错误信息%s\n,strerror(ret3)); return -1; } printf(创建线程3成功,线程3ID:%ld\n,tid3); //请求取消指定的线程1 int ret_cancel pthread_cancel(tid1); //只能说明请求取消成功不能说明会被立即取消 if(ret_cancel ! 0) { fprintf(stderr,请求取消线程1失败,错误信息%s\n,strerror(ret_cancel)); return -1; } printf(请求取消线程1成功\n); //请求取消指定的线程2 int ret_cancel2 pthread_cancel(tid2); if(ret_cancel2 ! 0) { fprintf(stderr,请求取消线程2失败,错误信息%s\n,strerror(ret_cancel2)); return -1; } printf(请求取消线程2成功\n); //请求取消指定的线程3 int ret_cancel3 pthread_cancel(tid3); if(ret_cancel3 ! 0) { fprintf(stderr,请求取消线程3失败,错误信息%s\n,strerror(ret_cancel3)); return -1; } printf(请求取消线程3成功\n); //阻塞等待线程退出 pthread_join(tid1,NULL); pthread_join(tid2,NULL); pthread_join(tid3,NULL); return 0; }