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

如何用信号量替代pthread_join同步线程并修改C四次方根求和程序

用信号量替代pthread_join实现线程同步的C程序修改方案

修改思路

要替代pthread_join实现主线程等待所有计算线程完成,我们可以用计数信号量:初始化信号量值为0,每个子线程完成所有任务后给信号量"发信号"(sem_post),主线程则通过等待信号量达到指定次数(等于线程数m)来确认所有子线程结束。

修改后的完整代码

#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <semaphore.h>  // 新增信号量头文件

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;  // 互斥锁,保护全局总和
sem_t done_sem;  // 计数信号量,用于主线程等待所有子线程完成
int chunk_size;  // 每个线程要计算的整数个数
double total_sum = 0.0;  // 全局共享总和

void *calc(void *arg) {
    long tid = (long)arg;
    double partial_sum = 0.0;
    // 计算当前线程负责的整数范围:从tid*chunk_size +1 到 (tid+1)*chunk_size
    for (int i = tid * chunk_size + 1; i <= (tid + 1) * chunk_size; i++) {
        partial_sum += pow(i, 0.25);  // 累加四次方根
    }
    printf("线程 %ld: 部分和 = %lf\n", tid, partial_sum);

    // 互斥锁保护全局总和的累加操作
    pthread_mutex_lock(&mutex);
    total_sum += partial_sum;
    pthread_mutex_unlock(&mutex);

    // 子线程完成任务,给信号量加1
    sem_post(&done_sem);
    pthread_exit(NULL);  // 显式退出线程
}

int main(int argc, char *argv[]) {
    if (argc != 3) {
        fprintf(stderr, "用法: %s <线程数m> <整数上限n>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    int m = atoi(argv[1]);
    int n = atoi(argv[2]);
    chunk_size = n / m;
    pthread_t threads[m];

    // 初始化信号量:初始值为0,仅当前进程内线程可见
    if (sem_init(&done_sem, 0, 0) != 0) {
        perror("sem_init 失败");
        exit(EXIT_FAILURE);
    }

    // 创建m个计算线程
    for (long i = 0; i < m; i++) {
        if (pthread_create(&threads[i], NULL, calc, (void*)i) != 0) {
            perror("pthread_create 失败");
            exit(EXIT_FAILURE);
        }
    }

    // 主线程等待所有m个子线程完成:调用m次sem_wait,每次等待信号量值≥1
    for (int i = 0; i < m; i++) {
        sem_wait(&done_sem);
    }

    // 输出最终总和
    printf("所有数的四次方根总和: %f\n", total_sum);

    // 清理资源:销毁信号量和互斥锁
    sem_destroy(&done_sem);
    pthread_mutex_destroy(&mutex);

    return EXIT_SUCCESS;
}

关键修改点说明

  • 新增信号量相关代码:引入<semaphore.h>头文件,定义全局信号量done_sem,主线程中用sem_init初始化(初始值0),子线程结束前调用sem_post递增信号量,主线程通过sem_wait等待所有子线程的信号。
  • 资源清理:主线程最后销毁信号量和互斥锁,避免资源泄漏。
  • 错误处理:增加了命令行参数检查、信号量初始化和线程创建的错误判断,提升程序健壮性。
  • 变量命名优化:把原代码中模糊的变量名改成更清晰的名字,增强代码可读性。

编译与运行

编译时需要链接pthread和math库:

gcc -o program program.c -lpthread -lm

运行命令:

./program 2 65536

内容的提问来源于stack exchange,提问作者Sreehas Dommata

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 05:35:29