pthread_create需显式设置栈大小以防溢出,共享变量必须加锁避免竞态,线程退出后须pthread_join或pthread_detach清理资源,信号与多线程交互应避免pthread_kill而改用条件变量或事件通信。
很多初学者直接传 NULL 给 pthread_create 的第四个参数(线程属性),以为系统会自动分配,结果在线程函数里一用局部变量就崩溃。这不是随机错误,而是因为默认栈大小通常只有 2MB(Linux 下),且无法动态扩展;若线程递归过深或分配大数组(比如 char buf[1024*1024]),就会触发栈溢出,segfault 或静默破坏相邻内存。
实操建议:
malloc 分配堆内存,并确保线程退出前 free
pthread_attr_setstacksize 显式设置,例如:pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, 8 * 1024 * 1024); // 8MB
pthread_create(&tid, &attr, thread_func, arg);
pthread_attr_destroy(&attr);
PTHREAD_STACK_MIN(通常是 16KB),也不能超过系统限制(ulimit -s)int counter = 0; 被两个线程同时执行 counter++,最终结果大概率是 1 而不是 2——这不是概率问题,是 counter++ 在汇编层面至少包含三步:读取、加 1、写回。两个线程可能交错执行这三步,造成一次更新被覆盖。
常见误判:
volatile 只禁用编译器优化,不阻止 CPU 重排序,也不提供原子性或内存屏障正确做法:对共享变量的读写,统一用 pthread_mutex_t 保护;若只是计数,可考虑 __atomic_add_fetch(GCC 内置原子操作),但要注意平台兼容性。
调用 pthread_create 后不调用 pthread_join,线程变成“分离状态”以外的“可连接线程”(joinable)。这类线程结束后,其退出状态、栈内存等资源不会自动释放,直到有其他线程调用 pthread_join。长期运行的程序若漏掉 pthread_join,会持续泄漏资源,最终 pthread_create 返回 EAGAIN(资源耗尽)。
两种处理路径:
pthread_join(tid, &retval)
pthread_detach(pthread_self()),之后无需 join;但要注意,分离后不能再被 join,也不能获取其返回值exit() 前遗漏 join —— exit 会终止整个进程,未 join 的 joinable 线程资源仍不释放用 pthread_kill(tid, SIGUSR1) 向某线程发信号,看似精准,实际风险极高:信号可能被任意线程接收(取决于信号掩码和调度),且若目标线程正阻塞在 read 或 pthread_cond_wait 上,行为不可控;更严重的是,signal 处理函数是全局的,多个线程同时收到同信号,会共用同一个 handler,引发数据竞争。
替代方案更可靠:
pthread_cond_signal + pthread_mutex_t 实现线程间通知(推荐)poll 等待sigwait 在指定线程中同步等待,且提前用 pthread_sigmask 屏蔽其他线程接收该信号信号与线程模型本身不正交,C 标准库对多线程信号的支持非
