Skip to content
← 返回C列表
知识专题

C POSIX 线程:创建、互斥与退出前收拢 ​

前置:C指针与对象生存期。jobs、scan和run来自双文件统计库的scan.c;先确认谁持有参数,再推演线程结束与销毁顺序。

示例未执行;下文现象与检查条件用于源码推演。

专题入口:C POSIX 文件接口:描述符、短读写与错误契约 · C POSIX 线程:创建、互斥与退出前收拢 · C POSIX 完整实践:双文件字节统计库 · C POSIX 排错:系统错误、死锁与不完整输出

C线程参数为什么不能指向短命栈变量 ​

C线程参数为什么不能指向短命栈变量:pthread_create 可能在调用返回之前就开始运行新线程。必须先初始化 jobs 的 path 与 owner,再创建线程;参数对象的生存期必须覆盖线程结束。项目把 jobs 放在堆上的 scan 中,run 在返回之前 join,destroy 只允许在 run 之后同一拥有者调用。

不能在循环里把同一个局部 i 的地址交给所有线程,也不能从启动函数返回时释放它们还在使用的状态。线程调度顺序不确定,不能根据屏幕上偶尔观察到的顺序推断安全。

C部分线程创建失败如何清理 ​

C部分线程创建失败如何清理:started 只记录成功创建的线程数。第二次创建失败时,第一次线程仍可能正在读取;run 必须对 threads[0..started) 执行 pthread_join,收拢后再返回创建错误。失败的线程ID未初始化,不能参与 join。

线程只能由本拥有者 join 一次,不能同时让另一个线程 join 或 detach。join 失败不是“线程已结束”的证据;本例把这种内部不变式破坏视为致命错误并 abort,绝不继续 free 仍可能被使用的内存。普通资源不足由创建错误返回,致命路径不是业务恢复策略。

C互斥锁应该保护哪些状态 ​

C互斥锁应该保护哪些状态:两个 worker 都可能更新 total,读取、检查溢出、加法与写回必须处于同一个 pthread_mutex_lock 临界区。只锁赋值会让两线程都读到旧值;volatile 也不能让复合更新成为原子操作。每个 worker 的局部 bytes 不共享,因此读取文件时不持锁。

本例只有一把默认非稳健互斥锁,不使用递归重入或拥有者死亡恢复。lock/unlock 不应在满足这些约束的正常路径失败;不满足时中止。若改成 robust mutex,EOWNERDEAD 表示已取得锁但数据可能不一致,需要新恢复协议,不能直接沿用这里的 require_success。

C主线程何时可以读取工作线程结果 ​

C主线程何时可以读取工作线程结果:join 完成后主线程再读每个 worker 的 error,不能边运行边无锁轮询。total 的并发写由 mutex 串行化,最终读取在全部 join 后;ready 只由主线程在全部成功后设为1。即使另一个线程已成功累加,任一失败也不发布报告。

attempted 在启动前置位,使 run 是一次性状态机:created → attempted → ready 或 failed。失败不支持重试,避免重复累计;第二次调用返回 EALREADY。此句柄不允许外部并发调用,内部有锁不代表所有公开操作都线程安全。

独立练习 ​

第二次 create 失败时列出可以 join 的ID。若把 join 移到 mutex 临界区内部,会怎样?失败后为什么拒绝第二次 run?

先写出状态和资源归属,再对照答案;这些是推演练习,没有执行示例。

参考解答与检查条件

只能join第一次成功创建的ID。worker结束前要取同一锁,持锁join会互等。一次性状态避免把第一次部分累计混进第二次结果;失败也先收拢线程再返回。

资料与适用边界 ​

2026-10-17 核对 Linux read 手册、write 手册、close 的平台差异、pthread_create、pthread_join 与 POSIX mutex 规范镜像。Linux 手册中的实现差异不直接推广为 macOS 实测结果。The Open Group 的 POSIX 页面本次抓取被拒绝,不记为已成功核读。线程依赖的目标表达参考 CMake 3.20 FindThreads,没有执行它来探测本机。

C++ 链接与拥有关系参照 cppreference language linkage、unique_ptr;中文核对 Microsoft extern 说明,仅引用语言链接概念,不套用其 Windows 编译开关。文章采用独立组织的边界与失败推演,外链用于溯源,必要答案已在正文。

继续阅读