Post

线程

线程

1. 线程的引入

  • 多个进程协作完成任务,需要进程间通信,本质是系统调用,需要较多的时间和CPU资源开销;并且进程切换需要同时切换资源、内存、寄存器
  • 进程 = 资源 + 指令执行序列
    • 采用线程保留了并发的优点,避免了进程切换代价
    • 实质就是内存映射表与资源不变,而PC指针和基本寄存器改变
  • 线程:进程中代码执行的一个序列
    • 是使用CPU的基本单元,由线程ID程序计数器PC寄存器组构成
    • 一个进程中至少存在一个线程
    • 从一个程序的逻辑功能角度,可以将进程划分成n个执行序列;这些序列可以独立,也可以有一定的关联关系
    • 在一个进程的生命周期中,可以创建n个线程

2. 多线程模型

  • 分类
    • 用户级线程(ULT)
      • 受内核支持,但不需内核管理
    • 内核级线程(KLT)
      • 由操作系统直接支持和管理

多对一模型

用户级线程模型

  • 管理是由线程库在用户空间进行的,内核并无感知
    • 线程间占用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.