Files
leetcode-go/笔试/微派 Test1/06-单选题4-线程资源.md
T

3.5 KiB

tags, create time
tags create time
笔试
微派
操作系统
线程
内存
2026-05-16 15:00

06 - 单选题 4:线程的资源隔离

题目

在同一进程中创建的多个线程之间,以下哪一项资源是不共享的?

选项 内容
A 堆(Heap)内存
B 文件描述符表
C 栈(Stack)空间
D 信号处理函数
点击查看答案与解析

✅ 正确答案:C


详细解析

进程 vs 线程的资源划分

graph TD
    %%{init: {'theme':'base','themeVariables': {'tertiaryColor':'#f0f4f8'}}}%%
    P["🏢 进程地址空间"]

    subgraph SH ["▸ 所有线程共享"]
        HEAP["📦 堆 Heap"]
        DATA["📄 数据段<br/>全局/静态变量"]
        BSS["📜 BSS 段<br/>未初始化全局变量"]
        CODE["🔧 代码段 .text"]
        FD["📋 文件描述符表"]
        SIG["⚙️ 信号处理函数"]
        CWD["🏠 当前工作目录"]
    end

    subgraph PT ["▸ 每个线程独有"]
        ST1["📚 栈 Stack"]
        REG["🎛️ 寄存器集合"]
        PC["💻 程序计数器 PC"]
        TLS["🔒 线程本地存储 TLS"]
        ERRNO["🚩 错误号 errno"]
    end

    SEP["━━━━━━━━ 分 隔 ━━━━━━━━"]

    ALL[". . . 所有线程可见 . . ."]
    T1["线程 1"]
    T2["线程 2"]
    T3["线程 3"]

    SH --> ALL
    PT --> T1
    PT --> T2
    PT --> T3

    style SH fill:#e8f5e9,stroke:#4caf50,color:#1b5e20
    style PT fill:#fff3e0,stroke:#ff9800,color:#e65100
    style SEP stroke-dasharray: 5 5,fill:#fafafa,stroke:#bbb
    style ALL stroke:none,fill:none,color:#999
    style T1,T2,T3 stroke:none,fill:none,color:#999

逐项分析

选项 正误 原因
A ❌ 不选 堆是共享的。所有线程通过相同的堆指针访问堆内存,所以动态分配的内存对所有线程可见。这也是为什么多线程并发访问同一堆对象需要加锁
B ❌ 不选 文件描述符表是共享的。open() 返回的文件描述符对所有线程有效,一个线程打开的文件可以在另一个线程中关闭
C ✅ 正确 每个线程有自己独立的栈空间! 每个线程调用函数时的局部变量、返回地址、函数参数都在自己的栈上。互不干扰
D ❌ 不选 信号处理函数是共享的。注册了一个信号处理器后,该进程的所有线程都会响应这个处理逻辑

为什么每线程独立栈?

这是设计上的必然选择:

  1. 函数调用需要局部变量隔离: foo() 在线程 1 中的 x = 42 不应该影响线程 2 中的 x
  2. 返回地址独立: 每个线程调用同一个函数,返回地址各自不同
  3. 防止栈溢出牵连其他线程: 如果一个线程的栈爆了,不会影响其他线程的执行

对比:进程 vs 线程

资源 进程间 线程间
地址空间 ❌ 独立 ✅ 共享
堆 ❌ 独立 ✅ 共享
栈 ❌ 独立 ❌ 独立(每线程一块)
文件描述符 ❌ 独立(可inherit via fork) ✅ 共享
通信成本 高 (IPC) 低(直接读写共享内存)

[!tip] Go 语言的 goroutine 区别 Goroutine 和线程类似——每个 goroutine 有自己的栈。但 Go 使用可增长的栈(初始仅 2KB),且调度器从用户态出发,比系统级线程更轻量。