一. 线程概念
1. Linux线程
1. 在传统的操作系统中, 进程就是一个运行中的程序的描述信息 --- pcb, 控制程序的运行
2. 在Linux下的线程使用进程来模拟, 每个线程都是一个pcb, 同个进程中的线程共用虚拟地址空间, 进程就是一个线程组, 其 中至少有一个线程
3. 因为cpu运行调度pcb, 所以线程是cpu调度的基本单位
因为多个线程共用虚拟地址空间是一个进程(线程组), 所以进程是cpu分配资源的基本单位
4. Linux中线程被称为轻量级进程 (LWP, light weight process)
2.Linux线程 和 进程
线程数据的独有与共享:
1.线程共享的数据: 文件描述符表, 信号处理方式, 当前工作目录, 用户id和组id, 部分虚拟地址空间(代码段, 数据段)
2.线程独有的数据: 栈, 寄存器, 信号屏蔽字, errno, 线程id
线程的优缺点:
1. 线程的优点: 线程共享虚拟地址空间, 所以线程间通信更加方便
创建 / 销毁线程的开销小
提高程序的并发性
2. 线程的缺点: 缺乏访问控制, 在一个线程中操作不当会影响其他线程
健壮性降低, 单个线程出现异常, 整个进程都崩溃
二. POSIX线程库
1. 线程创建
功能:创建一个新的线程
原型
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)
(void*), void *arg);
参数
thread:返回线程ID
attr:设置线程的属性,attr为NULL表示使用默认属性
start_routine:是个函数地址,线程启动后要执行的函数
arg:传给线程启动函数的参数
返回值:成功返回0;失败返回错误码
// 返回当前线程id
pthread_t pthread_self(void);
pthread_create中的参数 thread 线程id , pthread_self 的返回值线程 id 和 ps -eLf 查看到的线程id指的不是一个id
1. ps 命令中的id是用来唯一标识线程的一个整型变量, 因为cpu要调度线程, 通过id来标识线程, 和进程id同一类型pid_t
而且进程id一定等于其中一个线程id, 因为线程组ID总是和主线程的线程组Id一致
2.程序中返回的线程id, 指向一个虚拟内存单元,该内存单元的地址即为新创建线程的线程Id, 线程库的后续操作,就是根据该线程Id来操作线程的, pthread_t类型本质就是一个进程地址空间上的一个地址
2. 线程终止
功能:线程终止
原型
void pthread_exit(void *value_ptr);
参数
value_ptr:value_ptr退出的返回值, 不要指向一个局部变量。
返回值:无返回值
功能:取消一个执行中的线程
原型
int pthread_cancel(pthread_t thread);
参数
thread:线程ID
返回值:成功返回0;失败返回错误码
一个线程可以调用pthread_ cancel终止同一进程中的另一个线程
注意点:
1. 不要用exit()退出线程, exit()退出的是进程
2. 其他线程可以使用 return 退出, 主控线程使用return相当于调用exit()
3. 主控线程用pthread_exit(), 子线程可以用return和pthread_exit()
3. 线程等待
功能:等待线程结束
原型
int pthread_join(pthread_t thread, void **value_ptr);
参数
thread:线程ID
value_ptr:它指向一个指针,后者指向线程的返回值
返回值:成功返回0;失败返回错误码
一个线程启动有一个默认属性joinable, 处于joinable状态的线程退出后不会自动释放资源, 需要被其他线程等待
调用pthread_join()的线程将挂起等待,直到id为thread的线程终止。thread线程以不同的方法终止,通过pthread_join得到的终止状态是不同的:
1. 如果thread线程通过return返回,value_ ptr所指向的单元里存放的是thread线程函数的返回值
2. 如果thread线程是自己调用pthread_exit终止的,value_ptr所指向的单元存放的是传给pthread_exit的参数
3. 如果对thread线程的终止状态不感兴趣,可以传NULL给value_ ptr参数
4. 如果thread线程被别的线程调用pthread_ cancel异常终掉,value_ ptr所指向的单元里存放的是常数PTHREAD_
CANCELED
4. 线程分离
默认情况下,新创建的线程是joinable的,线程退出后,需要对其进行pthread_join操作,否则无法释放资
源,从而造成系统泄漏。如果不关心线程的返回值,join是一种负担,这个时候,我们可以告诉系统,当线程退出时,自动释放线程
资源。
int pthread_detach(pthread_t thread);
//1. 可以进入子线程时, 自己分离自己
pthread_detach(pthread_self());
//2. 也可以父进程创建时, 分离子线程
pthread_detach(tid)