一些历史背景
Linux 间接起源于 Unix,而 Linux 诞生时并不存在 "线程" 的概念
在 20 世纪 90 年代线程才流行起来,POSIX Thread 标准于 1995 年确立
Unix 中引入 Thread 之后,大量函数被重写,信号机制也变得复杂
2005 年之后,处理器生成厂商向超线程和多核架构靠拢
一些常见的概念
物理处理器:安装在主机上的真实的处理器硬件
逻辑处理器:逻辑处理器与超线程技术相关
- 不支持超线程:逻辑处理器的数量等于核心数的数量
- 支持超线程:逻辑处理器的数量是处理器核心数的两倍
核心数:即多核处理器中的内核数量
- 通过工艺手段将多个完整的 CPU 塞进一个处理器封装中 (每个 CPU 就是一个核)
线程与进程的关系
进程:应用程序的一次加载执行 (系统进行资源分配的基本单位)
线程:进程中的程序执行流
- 一个进程中可以存在多个线程 (至少存在一个线程)
- 每个线程执行不同的任务 (多个线程可并行执行)
- 同一个进程中的多个线程共享进程的系统资源
进程中的多个线程并行执行,共享进程资源!
初探线程编程模型
多线程 vs 多进程
创建 / 销毁 线程花费的时间 < 创建 / 销毁 进程花费的时间
多线程切换开销 < 多进程切换开销
线程间数据共享复杂度 < 进程间数据共享复杂度
多线程代码稳定性 < 多进程代码稳定性
多线程代码复杂度 > 多进程代码复杂度
Linux 多线程 API 函数
头文件:#include<pthread.h>
线程创建函数:int pthread_create(pthread_t* thread, const pthread_attr_t* attr, void* (*start_routine)(void*), void* arg);
- thread:pthread_t 变量的地址,用于返回线程标识
- attr:线程的属性,可设置为 NULL,即:使用默认属性
- start_routine:线程入口函数
- arg:线程入口函数参数
线程标识:
- pthread_t pthread_self(void);
- 获取当前线程的 ID 标识
线程等待:
- int pthread_join(pthread_t thread, void** retval);
- 等待目标线程执行结束
多线程编程示例
实验一:性能对比
相同功能的 多线程程序 vs 多进程程序
对比项:创建 / 销毁
实验二:数据共享
多线程程序共享一段内存 => "全局变量"
多进程程序共享一段内存 => "机制复杂"