线程概念与多线程函数
一、线程的概念1.1 Linux线程本质对比维度传统进程线程LWP内核数据结构一个task_struct每个线程对应一个独立的task_struct地址空间 (mm_struct)独立拥有共享同一进程的mm_struct文件描述符 (files_struct)独立拥有共享同一进程的files_struct信号处理表 (signal_struct)独立拥有共享同一进程的signal_struct内核视角独立的调度单元本质也是独立的调度单元资源独立性资源隔离互不干扰资源共享通信方便但需同步本质描述独立的进程地址空间下的调度单元同一进程地址空间下的多个调度单元Linux 内核没有独立的“线程”数据结构线程就是共享资源的轻量级进程多个线程对应多个task_struct但共用同一个mm_struct等核心资源。进程是资源分配的基本单位线程是执行调度的基本单位1.2 线程的状态状态状态码核心描述典型触发场景后续行为运行状态R(Running)正在 CPU 执行或等待 CPU 调度可运行正常执行指令、就绪队列中等待时间片被调度器选中后进入 CPU 执行可中断睡眠S(Interruptible Sleep)等待某个事件完成可被信号唤醒等待 I/O 操作、等待锁、sleep()系统调用事件完成或收到信号后变回R状态不可中断睡眠D(Uninterruptible Sleep)等待关键硬件操作完成不能被信号中断等待磁盘读写、硬件驱动操作防止数据损坏硬件操作完成后自动变回R状态停止状态T(Stopped)线程被暂停执行可被信号恢复收到SIGSTOP/SIGTSTP信号、被调试器暂停收到SIGCONT信号后恢复为R状态僵尸状态Z(Zombie)线程已终止但资源未被回收子线程退出但父进程未调用wait()/waitpid()父进程回收后变为X状态消失死亡状态X(Dead)线程彻底终止资源全部释放wait()回收僵尸态、线程正常退出且被回收瞬间状态几乎无法被观测到1.3 Linux线程与POSIX标准的兼容维度说明标准遵循完全遵循POSIX 线程标准提供与其他 UNIX-like 系统一致的线程接口确保多平台代码可移植性核心接口pthread_create线程创建、pthread_join线程等待等库依赖核心操作由libpthread.so动态库提供头文件编码时需包含#include pthread.h声明库中函数接口编译链接编译时需显式链接线程库gcc 源码.c -o 可执行文件 -lpthread否则会报“未定义引用”错误内核交互方式通过libpthread 库的 POSIX 接口操作线程而非直接调用内核系统调用用户态代码通过库封装与内核交互多线程的接口函数通过第三方库提供libpthread.so1.4 进程与线程的核心区别对比维度进程 (Process)线程 (Thread)资源独立性拥有独立的内存空间、文件描述符等系统资源共享所属进程的内存空间和资源仅拥有独立的栈、程序计数器等创建/切换开销开销大涉及资源分配与回收开销小仅需保存少量上下文信息通信方式需通过进程间通信IPC机制如信号、消息队列等可直接通过共享内存通信需同步机制避免冲突健壮性一个进程崩溃通常不影响其他进程一个线程崩溃可能导致整个进程崩溃适用场景• 任务间需要严格隔离如浏览器标签页• 充分利用多核CPU处理CPU密集型任务如大规模计算• 长时间运行的独立任务如后台备份、视频转码• 运行不稳定或第三方代码避免崩溃影响整体• 任务间需要频繁共享数据如Web服务器处理多请求• 轻量级并发追求低开销如GUI程序后台加载数据• I/O密集型任务如网络请求、文件读写可利用等待时间切换• 短期、协作紧密的子任务如数据分片处理后汇总二、多线程相关函数2.1 线程创建与终止函数2.1.1 pthread_create函数项目内容所需头文件#include pthread.h函数原型int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);功能在调用进程中创建一个新的线程参数 - thread用于存储新创建线程的唯一标识符线程ID参数 - attr用于指定新线程的属性若为NULL则使用系统默认属性参数 - start_routine指向线程的入口函数参数 - arg用于给线程入口函数传递参数若无需参数可设为NULL返回值 - 成功返回0新线程ID会写入thread指向的变量中返回值 - 失败返回非0错误码不等于0不能使用perror函数需要进行格式化输出2.1.2 pthread_exit函数项目内容所需头文件#include pthread.h函数原型void pthread_exit(void *retval);功能结束当前线程参数 - retval用来给回收资源的线程传递线程的退出状态值若不想返回退出状态值可以传NULL返回值无void2.2 线程标识函数2.2.1 pthread_self函数项目内容所需头文件#include pthread.h函数原型pthread_t pthread_self(void);功能获取调用线程的线程ID参数无返回值总是成功返回调用线程的线程ID2.3 线程回收函数2.3.1 pthread_join函数项目内容所需头文件#include pthread.h函数原型int pthread_join(pthread_t thread, void **retval);功能阻塞等待指定的结合态的线程结束为其回收资源参数 - thread存储要回收资源的线程ID参数 - retval用来接收线程退出的状态值不关心传NULL即可返回值 - 成功返回0返回值 - 失败返回非0错误码不等于02.3.2 资源回收管理模式线程创建后默认处于结合态若未显示设置为分离态其终止后资源不会立即释放必须由其他线程(通常是主线程)通过pthread_join( )主动回收分离态的线程终止后会由系统自动回收资源无需其他线程调用pthread_join( );对比维度结合态默认分离态资源回收方式必须通过其他线程调用pthread_join()回收线程终止后系统自动回收资源pthread_join()作用有效调用后阻塞直到目标线程终止并回收其资源无效调用会返回错误无法等待分离态线程未回收的风险若主线程未调用pthread_join()线程终止后会成为“僵尸线程”占用task_struct等资源无风险终止后资源立即释放不会产生僵尸线程状态设置时机/方式• 创建时默认无需额外操作• 也可通过pthread_detach()函数从结合态转为分离态在pthread_create()的attr参数中设置PTHREAD_CREATE_DETACHED适用场景需要获取线程退出状态的场景• 无需获取线程退出状态• 希望自动释放资源的场景2.3.3 pthread_attr_init函数项目内容所需头文件#include pthread.h函数原型int pthread_attr_init(pthread_attr_t *attr);功能将一个线程属性对象初始化为默认值参数 - attr需要被初始化的线程属性对象返回值 - 成功返回0返回值 - 失败返回非0错误码不等于02.3.4 pthread_attr_setdetachstate函数项目内容所需头文件#include pthread.h函数原型int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);功能设置线程属性对象的分离状态参数 - attr设置分离状态的线程属性对象参数 - detachstate用于指定线程的分离状态•PTHREAD_CREATE_JOINABLE将线程设置为结合态•PTHREAD_CREATE_DETACHED将线程设置为分离态返回值 - 成功返回0返回值 - 失败返回非0错误码不等于02.3.5 pthread_attr_destroy函数项目内容所需头文件#include pthread.h函数原型int pthread_attr_destroy(pthread_attr_t *attr);功能销毁一个已初始化的线程属性对象参数 - attr指定需要被销毁的线程属性对象返回值 - 成功返回0返回值 - 失败返回非0错误码不等于02.4 线程控制函数2.4.1 pthread_detach函数项目内容所需头文件#include pthread.h函数原型int pthread_detach(pthread_t thread);功能标记一个线程为分离态参数 - thread线程id返回值 - 成功返回0返回值 - 失败返回非0错误码不等于02.4.2 pthread_cancel函数项目内容所需头文件#include pthread.h函数原型int pthread_cancel(pthread_t thread);功能请求取消指定的线程目标线程对取消请求的处理取决于取消状态和取消类型参数 - thread要取消的线程ID返回值 - 成功返回0返回值 - 失败返回非0错误码不等于02.4.3 pthread_setcancelstate函数项目内容所需头文件#include pthread.h函数原型int pthread_setcancelstate(int state, int *oldstate);功能设置调用线程的可取消状态可取消状态值•PTHREAD_CANCEL_ENABLE可被取消默认•PTHREAD_CANCEL_DISABLE不可被取消参数 - state新的可取消状态参数 - oldstate旧的可取消状态用于保存之前的状态值返回值 - 成功返回0返回值 - 失败返回非0错误码不等于02.4.4 pthread_setcanceltype函数项目内容所需头文件#include pthread.h函数原型int pthread_setcanceltype(int type, int *oldtype);功能设置调用线程的可取消类型可取消类型值•PTHREAD_CANCEL_DEFERRED延时取消默认直到下一次调用能作为取消点的函数时才被取消•PTHREAD_CANCEL_ASYNCHRONOUS可被立即取消参数 - type要设置的新的可取消类型值参数 - oldtype存储旧的可取消类型值返回值 - 成功返回0返回值 - 失败返回非0错误码不等于0