线程基本概念
1、线程就是进程中的执行路线,即进程内部的控制序列,或者说进程的子任务(进程就是正在运行的程序,它是一个资源单位)。
2、线程是轻量级的,没有自己独立的内存资源,使用的是进程的代码、数据段、bss段、堆(注意没有栈),环境变量表、命令行参数、文件描述符、信号处理函数、工作目录、用户ID、组ID等资源。
3、线程拥有自己的独立的栈,也就是有自己独立的局部变量。
4、一个进程中可以同时拥有多个线程,即同时被系统调度的多条执行路线,但至少有一个主进程。
线程基本特点
1、线程是进程的实体,可作为系统独立的调度和分派的基本单位。
2、线程有不同的状态,系统提供了多种线程控制的原语(控制方法),比如:创建线程、销毁线程。
3、线程没有拥有自己的资源(唯一拥有的就是自己的栈空间),只拥有从属于进程的全部资源,所有资源分配都是面向进程的。
4、一个进程中可以有多个线程同时执行,它们可以执行相同的代码,也可以执行不同代码。
5、同一进程内的线程都在同一个地址空间下活动(0~4G),相对于多进程,多线程的系统开销小,任务切换快。
6、多进程协同工作时需要通信,而多线程间的数据交换不需要依赖类似IPC的特殊通信机制,简单而高效。
7、每个线程拥有自己独立的线程ID、寄存器信息、函数栈等。
8、线程之间也存在优先级。
POSIX线程
1、早期的UNIX操作系统是没有线程的,而是各计算机厂商提供了自己私有的线程库,不易于移植。
2、在1995年左右,定义了统一的线程编程接口,POSIX线程,即pthread。
3、pthread包含一个头文件pthread.h,一个共享库libpthread.so。
4、功能:
线程管理(创建/销毁、分离/联合、设置/获取线程属性)
线程同步(互斥):互斥量(互斥锁)、条件变量、信号量
线程函数
创建线程
#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:给线程入口函数传递的参数
运行的时候加参数 -lpthread
等待线程结束
int pthread_join(pthread_t thread, void **retval);
功能:等待线程结束获取线程入口函数的返回值,线程结束时该函数才返回。
thread:线程ID
retval:指针变量的地址,用于获取线程入口函数的返回值
注意:线程入口函数在返回数据时,不能返回指向私有栈空间的指针,如果获取到的是指向堆的指针,等待者要负责把该空间释放。(线程结束栈被销毁)
注意:当主线程结束,子线程会全部结束。
获取线程ID
pthread_t pthread_self(void);
功能:返回当前线程的ID(%lu)
比较两个线程ID
int pthread_equal(pthread_t t1, pthread_t t2);
功能:如果两个线程ID是同一个线程,则返回0,否则返回-1.
注意:pthread_t不一定是unsigned long类型,有些系统中它是结构体类型,所以无法使用==比较。
线程终止
void pthread_exit(void *retval);
功能:调用者线程结束(从入口函数return)
revtal:会返回给pthread_join第二个参数
注意:如果是进程的最后一个线程,当调用pthread_exit时进程也就结束了。
线程分离
非分离:线程可以被创建者调用pthread_join等待(回收资源)。
分离状态:线程不需要创建者等待,结束后自动释放资源。
int pthread_detach(pthread_t thread);
功能:调用线程与线程ID位thread线程成为分离状态
线程取消
int pthread_cancel(pthread_t thread);
功能:向指定的线程发送取消操作
注意:但对方不一定响应
设置调用者是否响应取消操作
int pthread_setcancelstate(int state, int *oldstate);
state:
PTHREAD_CANCEL_ENABLE 允许响应
PTHREAD_CANCEL_DISABLE 禁止响应
oldstate:获取旧的取消状态
设置线程属性
typedef union
{
char _size[_SIZEOF_PTHREAD_ATTR_T];
long int _align;
}pthread_attr_t;
猜测:不让手动修改线程的各大项属性,而使用pthread_attr_set/get系列函数来操作。
int pthread_attr_init(pthread_attr_t *attr);
功能:初始化线程属性
int pthread_attr_destroy(pthread_attr_t *attr);
功能:销毁线程属性
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
功能:设置线程属性中分离标志
int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate);
功能:获取线程属性中分离标志
PTHREAD_CREATE_DETACHED 分离
PTHREAD_CREATE_JOINABLE 不分离
int pthread_attr_setscope(pthread_attr_t *attr, int scope);
功能:设置线程属性中线程的竞争范围
PTHREAD_SCOPE_SYSTEM
PTHREAD_SCOPE_PROCESS
int pthread_attr_getscope(pthread_attr_t *attr, int *scope);
功能:获取线程属性中线程的竞争范围
int pthread_attr_setinheritsched(pthread_attr_t *attr,int inheritsched);
功能:设置线程属性的调度策略的来源
inheritsched:
PTHREAD_INHERIT_SCHED 继承创建者
PTHREAD_EXPLICIT_SCHED 单独设置
int pthread_attr_getinheritsched(pthread_attr_t *attr,int *inheritsched);
int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);
功能:设置线程的调度策略
SCHED_FIFO 先进先出策略
SCHED_RR 轮转策略
SCHED_OTHER 缺省
int pthread_attr_getschedpolicy(pthread_attr_t *attr, int *policy);
功能:获取线程属性中线程的调度策略
int pthread_attr_setschedparam(pthread_attr_t *attr,const struct sched_param *param);
功能:设置线程属性中线程的调度参数(优先级别)。
param: 最高级别0,就绪态
int pthread_attr_getschedparam(pthread_attr_t *attr,struct sched_param *param);
int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize);
功能:设置线程属性中栈尾的警戒区大小,默认一页
int pthread_attr_getguardsize(pthread_attr_t *attr, size_t *guardsize);
功能:获取线程属性中栈尾的警戒区大小
int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr);
功能:设置线程属性中栈底地址
int pthread_attr_getstackaddr(pthread_attr_t *attr, void **stackaddr);
功能:获取线程属性中栈底地址
int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);
功能:设置线程属性中线程的栈空间字节数
int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *stacksize);
功能:获取线程属性中线程的栈空间字节数
int pthread_attr_setstack(pthread_attr_t *attr,void *stackaddr, size_t stacksize);
功能:设置栈的地址和字节数
int pthread_attr_getstack(pthread_attr_t *attr,void **stackaddr, size_t *stacksize);
使用方法:
1、定义线程属性结构体
pthread_attr_t attr;
2、初始化线程属性结构体
pthread_attr_init(&attr);
3、使用pthread_attr_set系列函数堆结构体变量进行设置
4、在创建线程时(pthread_create函数的第二个参数中使用线程属性结构变量创建线程)
int pthread_getattr_np(pthread_t thread, pthread_attr_t *attr);
功能:获取指定线程的属性