基于枚举实现的Binary Semaphore程序输出异常,求排查原因
枚举实现二元信号量的多线程问题分析
你的代码存在三个核心问题,直接导致了运行行为不可预测和线程号垃圾值的问题:
1. 数组越界导致参数传递错误
main函数里的while(counter++<4)循环逻辑会引发数组越界:
- counter初始值为0,第一次循环后counter变为1,访问
threads[1]和ps[1]; - 当counter递增到4时,循环条件
4<4不成立,但此时已经执行了pthread_create(&threads[4], ..., &ps[4]),而threads和ps数组的下标范围是0-3,越界访问的内存属于未定义区域,里面的thread_num是垃圾值,这就是你看到奇怪线程号的直接原因。
2. 自定义信号量不具备线程安全性
你用枚举实现的wait()和signal()不是原子操作:
- 多个线程可能同时进入
while(s==IN_USE)的判断,因为判断和赋值s=IN_USE之间没有同步机制,会导致多个线程同时进入临界区,出现竞态条件,这也是输出混乱的原因之一。
3. 主线程提前终止导致子线程未执行
main函数创建完线程后直接return 0,会触发进程终止,此时所有子线程可能还没来得及执行就被系统强制杀死,这解释了为什么有时候没有任何输出。
修复后的示例代码
#include <stdio.h> #include <pthread.h> #include <semaphore.h> sem_t s; struct parameters{ int thread_num; }; void resource(void *params){ struct parameters *p = (struct parameters*)params; sem_wait(&s); // 替换自定义wait,保证原子操作 printf("Resource is being used by thread %d\n", p->thread_num); sem_post(&s); // 替换自定义signal } int main(void){ pthread_t threads[4]; struct parameters ps[4] = {{1}, {2}, {3}, {4}}; int counter; sem_init(&s, 0, 1); // 初始化二元信号量 for(counter = 0; counter < 4; counter++){ pthread_create(&threads[counter], NULL, resource, (void*)&ps[counter]); } // 等待所有线程执行完成 for(counter = 0; counter < 4; counter++){ pthread_join(threads[counter], NULL); } sem_destroy(&s); return 0; }
关键修复点
- 用
for循环替代原有的while循环,避免数组越界; - 使用pthread标准库的
sem_t信号量,保证wait和signal操作的原子性; - 调用
pthread_join等待所有子线程执行完毕,避免主线程提前终止。
内容的提问来源于stack exchange,提问作者FariyaAchhab
相关产品推荐
相关产品推荐

