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、程序计数器等。

✅ 多线程之所以高效,是因为共享资源减少了资源分配的开销。
❌ 但这也带来了并发访问的问题,必须通过同步机制来确保线程安全。

如果你在开发中遇到线程安全问题,记得使用 synchronizedReentrantLock 或者并发工具类来保护共享资源。


原始标题:How Do Threads Share Resources?