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

Ubuntu下C语言线程信号量实现数学运算的报错解决

C语言线程与信号量编程问题解决方案

问题描述

在Ubuntu上学习线程和信号量的C语言编程,目标是实现一个包含加法、乘法的数学运算程序,要求P4函数最后执行。已声明互斥信号量mutex和信号量prive,编写了P1-P4四个函数,但编译出现两类错误:

  1. pthread_create参数类型不兼容
  2. P3函数声明与定义类型冲突
    同时希望程序支持用户输入两个变量再执行运算。

原始代码

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>

void *P1(void *arg, int A, int B);
void *P2(void *arg, int A);
void *P3(void *arg, int S1, int S2);
void *P4(void *arg, int S3, int S2);

sem_t mutex, prive;

int S1 = 0, S2 = 0, S3 = 0, S4 = 0;
int A = 15;
int B = 10;

int main(){
pthread_t TID1, TID2, TID3, TID4;
printf("Main: ");

sem_init(&mutex, 0, 1);
sem_init(&prive, 0, 0);

pthread_create(&TID1, NULL, P1, NULL);
pthread_create(&TID2, NULL, P2, NULL);
pthread_create(&TID3, NULL, P3, NULL);
pthread_create(&TID4, NULL, P4, NULL);


pthread_join(TID1, NULL);
pthread_join(TID2, NULL);
pthread_join(TID3, NULL);
pthread_join(TID4, NULL);

sem_destroy(&mutex);
sem_destroy(&prive);
printf("S4= %d", S4);
}

void *P1(void *arg, int A, int B){
       sem_wait(&mutex);
       S1 = A + B;
       printf("S1= %d", S1);
       sem_post(&prive);
       pthread_exit(NULL);
       }

void *P2(void *arg, int A){
       sem_wait(&mutex);
       S2 = A + 4;
       printf("S2= %d", S2);
       sem_post(&prive);
       pthread_exit(NULL);
       }

void *P3(void *arg, int S2){
       sem_wait(&mutex);
       S3 = S2 * 2;
       sem_post(&prive);
       pthread_exit(NULL);
       }

void *P4(void *arg, int S3, int S2){
       sem_wait(&prive);
       sem_wait(&prive);
       S4 = S2 + S3;
       sem_post(&mutex);
       sem_post(&mutex);
       pthread_exit(NULL);
       }

编译报错信息

错误1:pthread_create参数类型不兼容

TP4_EXO3.c: 在函数‘main’中:
TP4_EXO3.c:24:1: 警告:传递‘pthread_create’的参数3时类型不兼容 [默认启用]
pthread_create(&TID1, NULL, P1, NULL);
^
从TP4_EXO3.c:3:0包含的文件:
/usr/include/pthread.h:244:12: 附注:期望‘void * (*)(void )’但实参的类型为‘void * ()(void *, int, int)’
extern int pthread_create (pthread_t *__restrict __newthread, //TID2、TID3、TID4同理//
^

错误2:P3函数类型冲突

TP4_EXO3.c: 在顶层:
TP4_EXO3.c:57:7: 错误:‘P3’的类型冲突
void *P3(void *arg, int S2){
^
TP4_EXO3.c:8:7: 附注:‘P3’的先前声明在此
void *P3(void *arg, int S1, int S2);
^

问题解决与代码修正

1. 修复pthread_create参数类型问题

pthread_create要求线程函数必须是void *(*)(void *)类型,即仅接受一个void*参数,返回void*。原代码中线程函数额外添加了int参数,不符合要求。

解决方式:利用全局变量直接访问运算所需的A、B、S1、S2等变量,无需额外传参,将所有线程函数的声明和定义修改为仅接受void* arg参数。

2. 修复P3函数声明与定义冲突

原代码中P3的声明为void *P3(void *arg, int S1, int S2);,但定义仅接受两个参数,参数数量不匹配。根据代码逻辑,P3仅使用S2计算S3,因此修正P3的声明为void *P3(void *arg);。

3. 添加用户输入功能

在main函数开头添加scanf语句,让用户输入A和B的值,替换原有的固定赋值。

4. 修正信号量逻辑确保P4最后执行

原信号量逻辑无法保证P4在P1、P2、P3全部完成后执行。调整为:

  • 将prive信号量初始值设为0
  • P1、P2、P3执行完成后各调用一次sem_post(&prive),累计发出3个信号
  • P4中调用三次sem_wait(&prive),等待所有前置任务完成后再执行

同时修正P4中错误的sem_post(&mutex)调用(P4未获取mutex,无需释放)。

修正后的完整代码

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>

// 符合pthread要求的线程函数声明
void *P1(void *arg);
void *P2(void *arg);
void *P3(void *arg);
void *P4(void *arg);

sem_t mutex, prive;

int S1 = 0, S2 = 0, S3 = 0, S4 = 0;
int A, B; // 等待用户输入

int main(){
    pthread_t TID1, TID2, TID3, TID4;
    
    // 获取用户输入
    printf("请输入两个整数A和B:");
    scanf("%d %d", &A, &B);

    // 初始化信号量:mutex初始为1(互斥锁),prive初始为0(等待前置任务完成)
    sem_init(&mutex, 0, 1);
    sem_init(&prive, 0, 0);

    // 创建线程
    pthread_create(&TID1, NULL, P1, NULL);
    pthread_create(&TID2, NULL, P2, NULL);
    pthread_create(&TID3, NULL, P3, NULL);
    pthread_create(&TID4, NULL, P4, NULL);

    // 等待所有线程结束
    pthread_join(TID1, NULL);
    pthread_join(TID2, NULL);
    pthread_join(TID3, NULL);
    pthread_join(TID4, NULL);

    // 销毁信号量
    sem_destroy(&mutex);
    sem_destroy(&prive);

    printf("\n最终结果:S4= %d\n", S4);
    return 0;
}

void *P1(void *arg){
    sem_wait(&mutex); // 获取互斥锁,保护全局变量
    S1 = A + B;
    printf("S1= %d\n", S1);
    sem_post(&mutex); // 释放互斥锁
    sem_post(&prive); // 通知P4任务完成
    pthread_exit(NULL);
}

void *P2(void *arg){
    sem_wait(&mutex);
    S2 = A + 4;
    printf("S2= %d\n", S2);
    sem_post(&mutex);
    sem_post(&prive);
    pthread_exit(NULL);
}

void *P3(void *arg){
    sem_wait(&mutex);
    S3 = S2 * 2;
    printf("S3= %d\n", S3);
    sem_post(&mutex);
    sem_post(&prive);
    pthread_exit(NULL);
}

void *P4(void *arg){
    // 等待P1、P2、P3全部完成
    sem_wait(&prive);
    sem_wait(&prive);
    sem_wait(&prive);
    S4 = S2 + S3;
    pthread_exit(NULL);
}

编译与运行

使用以下命令编译(必须链接pthread库):

gcc TP4_EXO3.c -o TP4_EXO3 -lpthread

运行程序后输入两个整数,即可看到各步骤结果及最终S4的值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 00:45:54