2. 多线程编程
??进程模型假设每个进程是具有单个控制线程的一个执行程序。几乎所有的现代操作系统都允许一个进程包含多个线程。
2.1 概述
- 每个线程是CPU使用的一个基本单元。
- 它包括线程ID、程序计数器、寄存器组和堆栈。它与同一进程的其它线程共享代码段、数据段和其它操作系统资源。
- 一个进程一般具有多个线程,那么进程能同时执行多个任务。
- 主线程
int main()
{
printf("hello world!");
}
??单线程进程和多线程进程如下图所示。
2.1.1 动机
??一个进程为什么要创建多个线程? ??1. 操作系统创建多个进程比一个进程中创建多个线程的开销大。 ??2. 进程间通信和线程间通信更复杂。
2.1.2 优点
??响应性: 如果一个交互程序采用多线程,那么即使部分阻塞或执行冗余操作,它仍然可以继续执行,从而增加对用户的响应程度。 ??资源共享: 进程只能通过如共享内存和消息传递之类的技术实现共享资源。而线程默认共享它们所属进程的内存和资源 ??经济: 进程创建所需的内存和资源分配非常昂贵。 ??可伸缩性: 对于多处理器体系结构,多线程的优点更大,因为线程可在多处理器核上并行运行。
2.2 多核编程
- 早期计算机是单核---->现代计算机是多核。
- 多核编程提供机制,以便更有效的使用这些多个计算核和改进并发性。
??下图所示的分别是单核系统和多核系统上的并行执行。
- 重点:并行与并发
并行性: 并行系统可以同时执行多个任务,指多核系统,多个进程同时执行的情况。 并发性: 并发系统也可以同时执行多个任务,指通过CPU上下文切换,执行多个任务的情况。 - CPU调度器通过快速切换系统内的进程,以便允许每个进程取得进展,从而提供并行假想。
2.3 多线程模型
- 有两种方法来提供线程支持:用户层的用户线程或内核层的内核线程。
? - 用户线程(user thread):位于内核之上,它的管理无需内核支持。 ? - 内核线程(kernel thread):由操作系统来直接支持与管理。
2.3.1 多对一模型
- 多对一模型: 映射多个用户级线程到一个内核线程。线程管理是由用户空间的线程库来完成,因此效率更高。
- 如果一个线程执行阻塞系统调用,那么整个进程将会阻塞。
- 因为任一时间只有一个线程可以访问内核,所以多个线程不能并行运行在多处理核系统上。
- 现代操作系统基本不使用该模型,因为它无法利用多个处理核。
2.3.2 一对一模型
- 一对一模型: 映射每个用户线程到一个内核线程。
- 该模型在一个线程执行阻塞系统调用时,能够允许另一个线程继续执行,所以它提供了比多对一模型更好的并发功能。
- 它也允许多个线程并行运行在多处理器系统上。
- 该模型的唯一缺点是:创建一个用户线程就要创建一个相应的内核线程,由于创建内核线程的开销会影响应用程序的性能。
2.3.3 多对多模型
- 多对多模型: 多路复用多个用户线程到同样数量或更少数量的的内核线程。
- 可以创建任意多的用户线程,并且相应内核线程在多处理器系统上并发执行,当一个线程执行阻塞系统调用时,内核可以调用另一个线程来执行。
- 双层模型: 是多对多模型的变种,仍然多路复用多个用户线程到同样数量或更少数量的内核线程,但也允许绑定某个用户线程到一个内核线程。即同时支持多对多模型和一对一模型。
?
2.4 线程库
??线程库(thread library)为程序员提供创建和管理线程的API。
2.5 线程池
??主要思想: 在进程开始时创建一定数量的线程,并加到池中等待工作。
??线程池的优点: ??? - 用现有线程服务请求比等待创建一个线程更快 ??? - 线程池限制了创建的线程数量 ??? - 将执行任务从创建任务的机制中分离出来
|