6. 线程
什么是线程?
LWP: light weight process 轻量级的进程,本质仍是进程(Linux环境下)
进程:独立空间地址,拥有PCB
线程:也有PCB,但是没有独立的地址空间(共享)
区别:在于是否共享空间地址
Linux下:线程:最小的执行单位
进程:最小的分配资源单位,可以看成是一个线程的进程
Linux内核线程实现原理:
- 轻量级进程(light-weight process),也有PCB,创建线程使用的底层函数和进程一样,都是
clone()
- 从内核里看进程和线程是一样的,都有各自不同的PCB
- 进程至少有一个线程
- 线程可以看作寄存器和栈的集合
- 在linux下,线程是最小的执行单位;进程是最小的资源分配单位
查看LWP(线程编号)号:
ps -Lf pid
查看指定线程的LWP号
线程共享资源
- 文件描述符表
- 每种信号的处理方式
- 当前工作目录
- 用户ID和组ID
- 内存地址空间(.text/.data/.bss/heap/共享库)
线程非共享资源
- 线程ID
- 处理器现场和栈指针(内核栈)
- 独立的栈空间(用户空间栈)
- errno变量
- 信号屏蔽字
- 调度优先级
获得错误码对应的错误信息:
char *strerror(int errnum);
线程的优点:
- 提高并发性
- 占用资源量小
- 通信方便
缺点
- 调试困难
- 库函数不稳定
- 对信号支持不好
有于Linux系统早期并没有线程,是在后期版本中加入,由于实现方法导致进程和线程差别不是很大
6.1 线程控制原语
6.1.1 获取线程IDpthread_self()
帮助手册:
man pthread_self
包含头文件:
#include <pthread.h>
函数原型:
pthread_t pthread_self(void);
函数说明:
获取线程ID.其作用对应进程中的
getpid()
函数。
线程ID:pthread_t
类型,本质:在Linux下为无符号整数(%lu),其他系统中可能是结构体实现
线程ID是进程内部识别标志。(两个进程间,线程ID允许相同)
注意:不应使用全局变量pthread_t tid
,在子线程中通过pthread_create
传出参数来获取线程ID,而应使用pthread_self
编译和链接时需加上-lpthread
参数 | 说明 |
---|---|
return |
返回调用线程的ID |
6.1.2 创建一个新线程pthread_create()
帮助手册:
man pthread_create
包含头文件:
#include <pthread.h>
函数原型:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
函数说明:
创建一个新线程。其作用,对应进程中
fork()
函数编译和链接时需加上
-lpthread
参数 | 说明 |
---|---|
thread |
新线程ID(传出) |
attr |
线程的属性信息(传入) |
start_routine |
线程执行的函数 |
arg |
函数执行的参数 |
return |
成功:0 失败:errno |
示例:创建一个线程:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <time.h>
void* thr(void *arg)
{
printf("I am a thread! pid = %d, tid = %lu\n", getpid(), pthread_self());
return NULL;
}
int main()
{
pthread_t tid;
pthread_create(&tid, NULL, thr, NULL);
printf("I am a main thread, pid=%d, tid=%lu\n", getpid(), pthread_self());
sleep(1);
return 0;
}
运行结果:
6.1.3 终止调用线程pthread_exit()
帮助手册:
man pthread_exit
包含头文件:
#include <pthread.h>
函数原型:
void pthread_exit(void *retval);
编译和链接时需加上
-lpthread
参数 | 说明 |
---|---|
retval |
退出值(传入) |
6.1.4 回收线程pthread_join()
帮助手册:
man pthread_join
包含头文件:
#include <pthread.h>
函数原型:
int pthread_join(pthread_t thread, void **retval);
函数说明:
阻塞等待回收
编译和链接时需加上
-lpthread
参数 | 说明 |
---|---|