线程
线程
1. 线程的引入
- 多个进程协作完成任务,需要进程间通信,本质是系统调用,需要较多的时间和CPU资源开销;并且进程切换需要同时切换资源、内存、寄存器
- 进程 = 资源 + 指令执行序列
- 采用线程保留了并发的优点,避免了进程切换代价
- 实质就是内存映射表与资源不变,而PC指针和基本寄存器改变
- 线程:进程中代码执行的一个序列
- 是使用CPU的基本单元,由线程ID、程序计数器PC、寄存器组和栈构成
- 一个进程中至少存在一个线程
- 从一个程序的逻辑功能角度,可以将进程划分成n个执行序列;这些序列可以独立,也可以有一定的关联关系
- 在一个进程的生命周期中,可以创建n个线程
2. 多线程模型
- 分类
- 用户级线程(ULT)
- 受内核支持,但不需内核管理
- 内核级线程(KLT)
- 由操作系统直接支持和管理
- 用户级线程(ULT)
多对一模型
用户级线程模型
- 管理是由线程库在用户空间进行的,内核并无感知
- 线程间占用CPU等协调工作由用户程序自行解决
- 任何时刻只有一个线程能访问内核(if necessary)
- 同一进程的线程不能运行在不同的CPU上
- 若一个线程执行了阻塞系统调用,则整个进程会被阻塞
- 线程表位于用户空间
一对一模型
内核级线程模型
- 用户创建的就是内核级线程(通过系统调用)
- 一个线程执行阻塞系统调用时,允许CPU切换给其他线程
- 所以,具有更好的并发能力
- 一个进程的不同线程可运行在不同的CPU上,实现多CPU的并行处理;但是创建内核线程的数量会影响系统性能,OS会限制线程总量
- 线程表位于内核空间
多对多模型
混合线程模型
3. 模型比较
用户级线程 | 内核级线程 | 用户+内核级 | |
---|---|---|---|
利用多核 | 差 | 好 | 好 |
并发度 | 低 | 高 | 高 |
切换代价 | 小 | 大 | 中 |
OS代码 | 无 | 大 | 大 |
用户灵活性 | 大 | 小 | 大 |
CPU资源分配 | 少 | 多 | 中 |
4. 线程库
- 为程序员提供的用来创建和管理线程的API
- 两种实现方法
- 用户线程库
- 在用户空间中提供一个没有内核支持的线程库,其所有代码和数据结构都存在于用户空间中
- 调用库中的一个函数只是导致了用户空间中的一个本地函数调用,而不是系统调用
- 编程语言提供的库函数
- 内核线程库
- 由操作系统直接提供的线程库,其所有代码和数据结构存在于内核空间中
- 调用库中的一个API函数通常会导致对内核的系统调用
- 操作系统提供的API
- 编程语言的线程库通常时对内核线程库进行更高级别的封装
- 用户线程库
- 分类
- (1) POSIX Pthread (2) 操作系统(如Win32) (3)高级语言(如Java)
- POSIX Pthread线程库
- 只是一种规范,不是具体实现
- Pthread是POSIX标准的扩展,可以实现为用户级或内核级的线程库
- Win32线程库
- Win32线程库是应用于Windows OS的内核级线程库
- Java线程库
- Java线程库允许在Java程序中直接创建和管理线程
- Java线程库跟随JVM运行在宿主OS中
- Java线程库使用宿主OS支持的线程库实现的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void printThread()
{
std::cout << "thread id: " << std::this_thread::get_id() << std::endl;
}
int main()
{
std::thread t1(printThread);
std::thread t2(printThread);
std::thread t3(printThread);
t1.join();
t2.join();
t3.join();
std::cin.get();
return 0;
}
This post is licensed under CC BY 4.0 by the author.