C/C++语言进阶-进程/线程/多线程《从进程到线程的实战技巧》
目录
六、C++ 标准库(推荐,跨平台)—— std::thread 及周边(C++11 / C++20 扩展)
一、进程(Process)
1. 定义
进程是程序运行的实例。
每启动一个可执行文件,操作系统就创建一个进程,分配独立的资源(内存、文件描述符、寄存器状态等)。
2. 特点
| 特征 | 说明 |
|---|---|
| 独立性 | 每个进程有独立的地址空间、堆、栈、全局变量 |
| 隔离性 | 一个进程崩溃通常不会影响其他进程 |
| 通信复杂 | 不同进程之间不能直接访问内存,需要 IPC(进程间通信)机制 |
3. 地址空间划分
进程的典型内存布局:
高地址
│
│ 栈(Stack) ← 局部变量、函数调用
│ 堆(Heap) ← 动态分配内存 malloc/new
│ 数据段(Data) ← 全局变量、静态变量
│ 代码段(Code) ← 程序指令
└────────────────
低地址
| 内存区域 | 内容 | 示例 | 是否线程共享 |
|---|---|---|---|
| 代码段 (Code) | 程序指令(函数体) | 函数定义、机器码 | ✅ 共享 |
| 数据段 (Data) | 全局变量、静态变量 | int g; static int s; |
✅ 共享 |
| 堆 (Heap) | 动态分配内存 | malloc()、new |
✅ 共享 |
| 栈 (Stack) | 局部变量、函数调用栈 | int local; |
❌ 每个线程独立 |
二、线程(Thread)
1. 定义
线程是进程中的执行单元。
同一进程内的多个线程共享进程资源(内存、文件句柄),但各自拥有独立的栈与寄存器。
⚙️ 线程是进程中的“执行单元”,是 CPU 调度的最小单位。
-
一个进程可以有多个线程(共享同一块内存)。
-
所有线程共享:
-
全局变量 / 堆内存
-
文件描述符 / I/O
-
-
每个线程有自己的:
-
栈空间
-
程序计数器(执行位置)
-
2. 特点对比
| 项目 | 是否共享 | 说明 |
|---|---|---|
| 代码段 | ✅ | 所有线程执行相同的程序指令 |
| 数据段 | ✅ | 全局变量、静态变量共用 |
| 堆内存 | ✅ | 一个线程分配的内存,别的线程也能访问 |
| 文件描述符 | ✅ | 打开的文件或 socket 共用 |
| 栈 | ❌ | 每个线程有独立的函数调用栈 |
| 程序计数器(PC) | ❌ | 每个线程的执行位置独立 |
三、POSIX 线程(pthread)
1. 创建线程
#include <pthread.h>
#include <stdio.h>
void* thread_func(void* arg) {
printf("子线程执行: %s\n", (char*)arg);
return NULL;
}
int main() {
pthread_t tid;
pthread_create(&tid, NULL, thread_func, "Hello Thread");
pthread_join(tid, NULL);
return 0;
}
2. 函数说明
| 函数 | 作用 |
|---|---|
pthread_create() |
创建线程 |
pthread_exit() |
退出当前线程 |
pthread_join() |
等待线程结束(阻塞) |
pthread_detach() |
分离线程(不等待) |
pthread_self() |
获取当前线程ID |
四、线程同步机制
线程共享内存,必须避免数据竞争(Data Race)。
🧩 一、为什么需要线程同步?
在多线程程序中,多个线程共享同一片内存,比如全局变量、堆区数据等。
如果两个线程同时修改同一个变量,就会出现 数据竞争(Data Race)。
📘 举个例子:
int counter = 0;
void* add_func(void* arg) {
for (int i = 0; i < 100000; i++) {
counter++; // 多线程同时执行这里
}
return NULL;
}
int main() {
pthread_t t1, t2;
pthread_create(&t1, NULL, add_func, NULL);
pthread_create(&t2, NULL, add_func, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
printf("最终结果:%d\n", counter);
}
👉 你可能以为结果是 200000,
但实际运行多次可能是 157634、199876、180231 …… 每次都不一样。
这是因为:
counter++不是一个原子操作,它其实包含了三步:1. 读取 counter 2. 加 1 3. 写回 counter
两个线程交叉执行就会「互相覆盖」数据,导致结果错误。
🔒 1、互斥锁(Mutex)—— 保护“不能同时进的门”
互斥锁(Mutex,Mutual Exclusion)就像一个「锁着的门」:
-
线程A 进入时要上锁;
-
如果线程B 也想进,被挡在门外;
-
A 干完事后解锁;
-
B 才能进去。
pthread_mutex_t lock; // 声明一个互斥锁
void* add_func(void* arg) {
for (int i = 0; i < 100000; i++) {
pthread_mutex_lock(&lock); // 上锁
counter++;
pthread_mutex_unlock(&lock); // 解锁
}
return NULL;
}
初始化与销毁
pthread_mutex_init(&lock, NULL);
...
pthread_mutex_destroy(&lock);
✅ 输出结果
多次运行结果都一样:
最终结果:200000
⚠️ 注意:
-
上锁和解锁必须成对出现;
-
如果一个线程上锁后忘了解锁,会导致其他线程永久等待(死锁);
-
同一个线程可以多次上锁的情况称为“递归锁”(需要特别设置)。
🕹️ 2、条件变量(Condition Variable)—— 线程之间的“信号灯”
有时候我们需要让一个线程等另一个线程干完某件事再继续。
这时,用互斥锁不够,还需要“条件变量”来当信号灯。
📘 场景例子:
我们有两个线程:
-
waiter()—— 等待信号; -
signaler()—— 发出信号。
pthread_mutex_t lock;
pthread_cond_t cond;
int ready = 0; // 状态标志
void* waiter(void* arg) {
pthread_mutex_lock(&lock);
while (!ready) { // 条件不满足就等待
pthread_cond_wait(&cond, &lock);
// 等待时会自动解锁,等信号来了会重新加锁返回
}
printf("waiter 收到信号,继续执行!\n");
pthread_mutex_unlock(&lock);
return NULL;
}
void* signaler(void* arg) {
sleep(1); // 模拟准备过程
pthread_mutex_lock(&lock);
ready = 1;
pthread_cond_signal(&cond); // 通知一个等待的线程
pthread_mutex_unlock(&lock);
return NULL;
}
main函数
int main() {
pthread_t t1, t2;
pthread_mutex_init(&lock, NULL);
pthread_cond_init(&cond, NULL);
pthread_create(&t1, NULL, waiter, NULL);
pthread_create(&t2, NULL, signaler, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
pthread_mutex_destroy(&lock);
pthread_cond_destroy(&cond);
}
💡 运行逻辑:
1️⃣ waiter 一开始发现 ready == 0,于是等待信号;
2️⃣ signaler 睡 1 秒后发信号;
3️⃣ waiter 被唤醒,输出:
waiter 收到信号,继续执行!
🧠 关键理解:
pthread_cond_wait()是「等待条件满足」的阻塞操作,
它必须和pthread_mutex_t一起使用,才能保证等待和修改状态是安全的。
⚖️ 3、信号量(Semaphore)—— 控制“能进多少人”
互斥锁相当于“一把锁”,一次只能进一个人。
信号量更灵活,可以同时允许多个线程访问资源。
比如一个“停车场”有 3 个车位,
信号量的初值设为 3,就表示最多同时 3 辆车能进去。
📘 示例:三个线程同时访问资源
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#include <stdio.h>
sem_t sem; // 声明信号量
void* task(void* arg) {
int id = *(int*)arg;
sem_wait(&sem); // 请求一个“许可”,车位 -1
printf("线程 %d 进入临界区\n", id);
sleep(2); // 模拟工作
printf("线程 %d 离开临界区\n", id);
sem_post(&sem); // 释放许可,车位 +1
return NULL;
}
int main() {
pthread_t t[5];
int ids[5] = {1,2,3,4,5};
sem_init(&sem, 0, 3); // 最多允许3个线程并发
for (int i = 0; i < 5; i++)
pthread_create(&t[i], NULL, task, &ids[i]);
for (int i = 0; i < 5; i++)
pthread_join(t[i], NULL);
sem_destroy(&sem);
}
✅ 输出示例:
线程 1 进入临界区
线程 2 进入临界区
线程 3 进入临界区
(等待2秒)
线程 1 离开临界区
线程 4 进入临界区
线程 2 离开临界区
线程 5 进入临界区
...
🧠 你可以这样理解:
信号量是「带计数的锁」:
sem_wait()相当于抢车位;sem_post()相当于开走腾出车位。
🔁 三者对比总结
| 机制 | 控制粒度 | 是否阻塞 | 用途 | 典型场景 |
|---|---|---|---|---|
| 互斥锁 (Mutex) | 一次一个 | 阻塞等待 | 防止数据竞争 | 多线程修改同一变量 |
| 条件变量 (Cond) | 逻辑事件 | 阻塞等待 | 等待条件成立 | 生产者/消费者模型 |
| 信号量 (Sem) | 可同时多个 | 阻塞等待 | 控制资源数量 | 限制并发访问数量 |
| 名称 | 作用 | 对应操作 |
|---|---|---|
| Mutex | 一次只让一个线程进入临界区 | lock / unlock |
| Condition | 线程等待特定事件 | wait / signal |
| Semaphore | 控制并发资源数量 | wait / post |
五、互斥锁的几种类型(按特性分)
在 Linux(pthread)里,互斥锁一共有 4 种类型:
🟩 1. 普通锁(NORMAL)
👉 特点:
-
同一个线程不能重复加锁,否则会死锁(卡死)。
-
简单、开销最小。
📘 适用场景:
一个函数里只加一次锁、解一次锁。
📗 示例:
pthread_mutex_t lock;
void* task(void* arg) {
pthread_mutex_lock(&lock);
printf("线程 %ld 进厨房炒菜\n", pthread_self());
sleep(1);
pthread_mutex_unlock(&lock);
return NULL;
}
int main() {
pthread_mutex_init(&lock, NULL);
pthread_t t1, t2;
pthread_create(&t1, NULL, task, NULL);
pthread_create(&t2, NULL, task, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
pthread_mutex_destroy(&lock);
}
🧩 运行效果:
两个线程轮流“炒菜”,不会同时操作厨房。
🟨 2. 检错锁(ERRORCHECK)
👉 特点:
-
如果同一个线程重复加锁,会报错(返回
EDEADLK),而不是卡死。 -
方便调试时发现错误。
📘 适用场景:
调试阶段,防止错误使用。
📗 示例:
pthread_mutex_t lock;
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
pthread_mutex_init(&lock, &attr);
pthread_mutex_lock(&lock);
printf("第一次加锁成功\n");
int ret = pthread_mutex_lock(&lock);
if (ret == EDEADLK)
printf("错误:同一个线程重复加锁\n");
pthread_mutex_unlock(&lock);
pthread_mutex_destroy(&lock);
🧩 输出:
第一次加锁成功
错误:同一个线程重复加锁
🟦 3. 递归锁(RECURSIVE)
👉 特点:
-
同一个线程可以重复加锁多次(比如函数递归调用时)。
-
需要加锁几次 → 解锁同样次数才能真正释放。
📘 适用场景:
函数 A 调用函数 B,而 A 和 B 都用同一把锁。
📗 示例:
pthread_mutex_t lock;
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&lock, &attr);
void nested() {
pthread_mutex_lock(&lock);
printf("nested() 也进来了\n");
pthread_mutex_unlock(&lock);
}
void work() {
pthread_mutex_lock(&lock);
printf("work() 加锁成功\n");
nested();
pthread_mutex_unlock(&lock);
}
int main() {
work();
pthread_mutex_destroy(&lock);
}
🧩 输出:
work() 加锁成功
nested() 也进来了
普通锁在这里会死锁,因为同一个线程重复加锁;
递归锁不会,因为它“记得是自己上的锁”。
🟥 4. 默认锁(DEFAULT)
👉 特点:
-
等价于普通锁(NORMAL)。
-
是
pthread_mutex_init()时默认的锁类型。
📗 示例:
pthread_mutex_t lock;
pthread_mutex_init(&lock, NULL); // 默认锁
🧩 四、总结对比表(通俗版)
| 类型 | 是否可重入 | 是否检查重复加锁 | 适合场景 | 是否易死锁 |
|---|---|---|---|---|
| NORMAL | ❌ 否 | ❌ 否 | 简单保护区 | ✅ 容易死锁 |
| ERRORCHECK | ❌ 否 | ✅ 是 | 调试、测试 | ❌ 不会死锁 |
| RECURSIVE | ✅ 是 | ✅ 是 | 递归调用 | ❌ 不会死锁 |
| DEFAULT | ❌ 否 | ❌ 否 | 默认使用 | ✅ 容易死锁 |
六、C++ 标准库(推荐,跨平台)—— std::thread 及周边(C++11 / C++20 扩展)
适用场景:大多数应用、跨平台代码库、现代 C++ 项目(Linux/Windows/macOS/嵌入式 Linux)
主要接口(C++11 起)
-
std::thread(线程) -
std::mutex,std::recursive_mutex,std::timed_mutex -
std::lock_guard,std::unique_lock,std::scoped_lock -
std::condition_variable,std::condition_variable_any -
std::future,std::promise,std::packaged_task,std::async -
std::atomic<T>(原子类型) -
std::call_once,std::once_flag -
thread_local(线程局部存储)
C++17 / C++20 补充
-
std::shared_mutex/std::shared_lock(读写锁) -
std::latch,std::barrier(C++20 同步栅栏) -
std::jthread(C++20,自动 join 并支持 stop token) -
<semaphore>:std::counting_semaphore(C++20) -
std::stop_token(协作取消)
示例合集(跨平台、标准库)
1) 基本线程:std::thread
#include <thread>
#include <iostream>
void worker(int id) {
std::cout << "worker " << id << " running\n";
}
int main() {
std::thread t1(worker, 1);
std::thread t2(worker, 2);
t1.join();
t2.join();
}
2) 互斥:std::mutex + lock_guard
#include <mutex>
#include <thread>
std::mutex m;
int counter = 0;
void inc() {
for (int i=0;i<10000;i++){
std::lock_guard<std::mutex> lk(m);
++counter;
}
}
3) 条件变量(producer-consumer)
#include <condition_variable>
#include <mutex>
#include <queue>
std::queue<int> q;
std::mutex m;
std::condition_variable cv;
bool done = false;
void producer() {
for (int i=0;i<10;i++) {
{
std::lock_guard<std::mutex> lk(m);
q.push(i);
}
cv.notify_one();
}
{
std::lock_guard<std::mutex> lk(m);
done = true;
}
cv.notify_one();
}
void consumer() {
while (true) {
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, []{ return !q.empty() || done; });
while (!q.empty()) {
int v = q.front(); q.pop();
// process v
}
if (done) break;
}
}
4) Future / Promise / async
#include <future>
#include <iostream>
int compute(int x){ return x*2; }
int main(){
std::future<int> fut = std::async(std::launch::async, compute, 21);
int r = fut.get();
std::cout << r << "\n"; // 42
}
5) 原子(高效计数器)
#include <atomic>
std::atomic<int> cnt{0};
void add(){ for(int i=0;i<10000;i++) cnt.fetch_add(1, std::memory_order_relaxed); }
6) 读写锁(shared_mutex)
#include <shared_mutex>
std::shared_mutex rw;
int shared_data = 0;
void reader() {
std::shared_lock<std::shared_mutex> lk(rw);
int v = shared_data; // 多个 reader 并行
}
void writer() {
std::unique_lock<std::shared_mutex> lk(rw);
shared_data++;
}
7) C++20:std::jthread 与 stop_token(优雅取消)
#include <thread>
#include <iostream>
#include <chrono>
void worker(std::stop_token st) {
while (!st.stop_requested()) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
std::cout<<"stopped\n";
}
int main(){
std::jthread t(worker);
std::this_thread::sleep_for(std::chrono::seconds(1));
t.request_stop(); // 发出取消请求
}
8) 信号量(C++20)
#include <semaphore>
std::counting_semaphore<10> sem(3); // 初始3
void task(){
sem.acquire();
// 临界区
sem.release();
}
七、面试常见问题
1 础概念类
-
什么是进程(Process)?什么是线程(Thread)?两者有什么区别?
-
进程:程序运行的实例,拥有独立的地址空间、资源(内存、文件句柄等)。 (GeeksforGeeks)
-
线程:进程内的执行单元(最小调度单位),同一进程的线程共享地址空间、资源。
-
区别:线程创建/切换比进程更轻;线程共享内存,进程一般隔离。 (ByteByteGo)
-
面试回答可以提及:内存共享差别、上下文切换开销、资源隔离、通信方式等。
-
-
为什么同一个进程中可以有多个线程?有什么好处?
-
多线程可以并发执行多个任务(尤其在多核或异步 I/O 场景)。
-
共享资源(如堆、全局变量、文件)减少开销。
-
提高响应性(例如 UI 线程 + 后台线程)或实现并行计算。 (0xkishan.medium.com)
-
-
线程与进程的生命周期/状态有哪些?
-
进程状态:新建 → 就绪 → 运行 → 阻塞/等待 → 终止。
-
线程状态(视平台而定):新建/可运行 → 运行 → 阻塞/等待 → 终止。
-
面试中可能问线程的 “新建 (created)/就绪 (runnable)/运行 (running)/阻塞 (blocked)/终止 (terminated)” 状况。 (Indeed)
-
-
什么是多线程 (Multithreading)?与多进程 (Multiprocessing) 有何区别?
-
多线程:在一个进程中运行多个线程,共享进程资源。
-
多进程:多个进程运行,各自拥有独立地址空间。
-
区别:资源开销、内存隔离、通信方式不同。 (finalroundai.com)
-
2 线程同步与并发安全
-
什么是数据竞争(Race Condition)?
-
当多个线程同时访问同一共享数据,并且至少一个是写操作,且访问不受同步机制保护,则可能出现数据竞争。
-
导致不可预测结果。
-
面试中常要求给出例子,比如
counter++在多线程中未加锁的场合。
-
-
什么是死锁 (Deadlock)?如何避免?
-
死锁:两个或多个线程互相等待对方释放资源,从而永久阻塞。
-
避免方法:
-
保持加锁顺序一致;
-
避免锁嵌套或使用递归锁时谨慎;
-
尽量缩短持锁时间;
-
使用定时锁、尝试锁(try_lock)等。
-
-
面试中经常考察死锁条件(互斥、占用且等待、循环等待、资源不可抢夺)和解决方法。
-
-
什么是线程同步?主要有哪些机制?
-
同步是控制线程间的执行顺序、防止资源冲突的技术。
-
常见机制:互斥锁 (mutex)、条件变量 (condition variable)、信号量 (semaphore)、读写锁 (shared_mutex)、原子操作 (atomic) 等。
-
面试中可能问「互斥锁 vs 读写锁」「条件变量如何工作」「信号量用途」等。
-
-
在 C++ 中如何管理线程安全?有哪些工具或接口?
-
std::mutex,std::lock_guard,std::unique_lock -
原子类型
std::atomic<T> -
条件变量
std::condition_variable -
读写锁
std::shared_mutex(C++17) -
线程局部存储
thread_local -
面试可延伸问「何时使用互斥锁,何时用原子操作」。
-
-
什么是原子操作 (Atomic operation)?在 C++ 中如何使用?
-
原子操作:不可分割的操作,执行过程不会被线程切换中断。
-
C++ 中常用
std::atomic<T>。 -
用于简单变量计数或标志,不需要完整锁机制。
-
面试中可能问
std::atomic的内存序 (memory_order) 概念、CAS (compare_and_swap) 等。
-
3 典型题目与深入考点
-
std::thread创建线程的方式?线程函数可以接受什么参数?-
std::thread t(func, arg1, arg2, …); -
参数可以是普通函数、成员函数、lambda 表达式、可调用对象。
-
注意传参方式(拷贝/引用)与线程生命周期管理(
join()/detach())。
-
-
std::thread::join()和detach()有什么区别?-
join():主线程等待子线程结束。 -
detach():子线程独立运行,主线程不等待;注意资源管理/线程结束问题。 -
面试可能问:detach 后如何保证线程资源被清理?何时使用。
-
-
解释
std::lock_guard<std::mutex>和std::unique_lock<std::mutex>的区别。-
lock_guard:简单、RAII 风格,只负责加锁-解锁,不可延迟解锁。 -
unique_lock:更灵活,可延迟加锁、提前解锁、转移锁所有权、支持std::condition_variable::wait()。 -
面试可能问为何不用裸
mutex.lock()/unlock()而用 RAII。
-
-
什么是线程池 (Thread Pool)?为什么使用?
-
线程池:预先创建若干线程,重复利用线程执行任务,而不是频繁创建销毁线程。
-
优点:减少线程创建销毁开销、限制线程数、控制资源。
-
面试可能问自己设计一个线程池的思路。
-
-
读写锁(shared_mutex)与互斥锁有什么区别?在什么场景下使用?
-
互斥锁:一次只一个线程访问资源。
-
读写锁:允许多个“读者”同时访问,但“写者”必须独占。
-
适用于读多写少的场景。
-
面试可能问“如果大量线程只读一个共享结构,你如何优化同步?”
-
-
线程优先级、亲和性(Affinity)、栈空间如何设置?(嵌入式/系统面试)
-
线程优先级:操作系统调度时考虑线程优先级。
-
亲和性:绑定线程到特定 CPU 核,有利于缓存一致性/性能。
-
栈空间:线程默认栈大小可能不适合嵌入式,应设置合理栈。
-
面试可能问“在嵌入式系统中你如何创建一个实时线程?用哪 API?需注意什么?”
-
-
对于多个线程修改同一个变量,你会如何处理?
-
方案:使用互斥锁保护、或者用
std::atomic。 -
面试关注:为啥不直接加锁?性能与延迟考虑。
-
注意细节:当操作复杂(多个变量或数据结构)时,单个原子变量不足。
-
-
栈内存、堆内存、全局变量在多线程中的区别是什么?
-
每个线程有自己独立的“栈”(函数调用、局部变量)。
-
进程堆、全局变量、静态变量在线程之间共享。
-
面试可能问“线程共享哪些?哪些不共享?”
(例如你之前提到“线程有自己的栈、程序计数器”)
-
-
优先级反转 (Priority Inversion) 是什么?怎么避免?
-
高优先级线程等待低优先级线程持有锁,而低优先级线程又被中优先级线程抢占,从而优先级最高的线程被“反转” 卡住。
-
避免方式:优先级继承 (priority inheritance)、限制锁持有时间、避免锁抢占。
-
面试中系统/嵌入式较为常见。
-
-
死锁、活锁 (Livelock)、饥饿 (Starvation) 区别?
-
死锁:线程互相等待资源,永不继续。
-
活锁:线程不停进行状态改变但没进展(忙等)。
-
饥饿:线程长期得不到资源,无法执行。
-
面试中常要求举例、提出解决方案。
-
-
C++ 内存模型 (C++11 及以后) 中的
happens-before关系是什么?为什么重要?-
用于定义多线程环境中操作的可见性和顺序保证。
-
std::atomic操作、锁操作都影响 happens-before 。 -
面试可能问
memory_order_relaxedvsmemory_order_seq_cst等。 -
来自高级/系统级面试题。 (aloa.co)
-
4 针对嵌入式/系统级工程师的补充题目
-
在嵌入式系统(Linux/RTOS)中创建线程要注意哪些?
-
栈大小、优先级、CPU 亲和性。
-
资源有限,避免大量线程、避免长时间锁。
-
实时调度策略(比如
SCHED_FIFO/SCHED_RR)与优先级继承。
-
-
进程间通信 (IPC) 和线程间通信有什么不同?
-
线程间:共享内存;速度快;但需同步。
-
进程间:一般通过管道、消息队列、共享内存 + 锁、socket 等;资源隔离更强。 (Those Pesky Bugs! Blog)
-
面试可能问“在你的项目里你为什么选线程而不是进程?”、“什么时候应使用进程而不是线程?”。
-
-
在 C++ 中,如何设置线程栈大小?如何获取线程本地句柄进行平台操作?
-
对于
std::thread:可以使用native_handle()获得底层平台句柄(如pthread_t或 WindowsHANDLE)。 -
在 POSIX 上:使用
pthread_attr_setstacksize()在创建线程时设置栈大小。 -
面试中可能问“如何在 Linux 上为线程指定特定栈大小?”。
-
-
线程池在嵌入式/高性能系统中的应用?设计思路?
-
固定线程数、任务队列、任务调度、线程复用。
-
避免频繁创建/销毁线程开销。
-
面试可能要求你“设计一个简单的线程池类”。
-
更多推荐
所有评论(0)