You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于枚举实现的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 11:42:03