1. 简介
线程通常被称为轻量级进程。它们在进程中执行特定任务。每个线程都有自己的 ID、寄存器集合、栈指针、程序计数器(PC)以及栈空间。
但线程之间也会共享资源,特别是在同一个进程内部。它们共享处理器、内存数据、文件描述符等资源。
本文将解释线程之间是如何共享资源的,以及需要注意的问题。
2. 资源与线程模型
要理解线程间的资源共享机制,我们首先来看一个进程的内存布局:
内存逻辑上可以划分为以下几个区域:
- 栈(Stack):存放局部变量、临时变量以及函数返回地址。
- 堆(Heap):用于动态分配内存。
- 代码段(Text/Code):存放可执行指令。
- 已初始化数据段(Initialized Data):存放已初始化的全局变量和静态变量。
- 未初始化数据段(Uninitialized Data / BSS):存放未初始化的静态变量。
2.1. 线程模型
线程模型有两种:单线程和多线程。
- 单线程进程:只有一个线程,只有一个程序计数器,只执行一个指令序列。
- 多线程进程:包含多个线程,它们共享部分资源,同时各自保留一些私有资源。
如下图所示,在一个包含多个线程的进程中,线程之间共享了哪些资源:
多线程的优势包括:
✅ 资源复用:操作系统无需为新线程重新分配内存映射,因为进程已经创建好了。
✅ 文件状态复用:不需要为每个线程单独维护文件状态。
❌ 并发风险:多个线程访问共享资源时必须确保线程安全,否则可能导致数据不一致。
3. 多线程进程中的资源共享机制
操作系统负责调度多线程进程中的所有线程。它维护了进程及其内部信息:
线程之间共享的资源包括:
私有资源 | 共享资源 |
---|---|
线程 ID | 代码段(Text/Code) |
寄存器 | 静态和全局数据(Data) |
栈指针 | 未初始化数据段(BSS) |
指令指针 | 文件描述符 |
栈空间 | 信号(Signals) |
信号掩码(Signal Mask) | 当前工作目录 |
调度策略或优先级 | 用户和组 ID |
3.1. 栈空间
线程的栈空间是私有的,但属于进程整体栈空间的一部分。
线程的栈中通常包含:
- 函数调用的参数
- 局部变量
- 返回地址(函数执行完后跳回的地址)
⚠️ 线程执行完毕后,其栈空间会被进程回收。因此,虽然每个线程都有自己的栈,但这些栈实际上是进程栈空间的子集。
3.2. 共享资源
线程共享以下资源:
- 代码段(Text):包含执行的机器指令。
- 数据段(Data):存放已初始化的静态变量。
- BSS 段:存放未初始化的静态变量。
- 堆(Heap):位于栈的反方向,用于动态内存分配。
✅ 线程之所以轻量,是因为这些资源在进程创建时已经分配好,线程只需复用即可,减少了资源分配的开销。
4. 总结
本文讲解了线程在同一个进程中是如何共享资源的。
- 共享部分:代码段、数据段、BSS 段、堆空间。
- 私有部分:栈空间、寄存器、线程 ID、程序计数器等。
✅ 多线程之所以高效,是因为共享资源减少了资源分配的开销。
❌ 但这也带来了并发访问的问题,必须通过同步机制来确保线程安全。
如果你在开发中遇到线程安全问题,记得使用 synchronized
、ReentrantLock
或者并发工具类来保护共享资源。