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

如何通过命令行参数设置数组大小?生产者消费者线程共享疑问

问题解答

1. 运行时确定缓冲区大小,必须用动态数组吗?

是的,你必须用动态内存分配(比如malloc)。因为固定大小的数组要求大小是编译时常量,而你的缓冲区大小是运行时通过命令行参数传入的,编译时无法确定,所以只能用动态分配。

你觉得“将数组大小关联到malloc分配的内存区域不太合理”其实是误解——malloc分配的内存是一块连续的、固定大小的区域,只要你在结构体里记录了buffSize,线程就可以通过这个值确定数组的边界,和固定大小数组的使用方式完全一致。动态分配只是内存的分配时机在运行时,本质上和固定数组一样是“固定大小”的缓冲区,只是内存不在栈上,而是在堆上。

所以你的思路没问题,用malloc是正确且必要的选择。

2. 为什么很多生产者消费者方案用全局缓冲区?

线程确实会共享父进程的所有内存(包括堆、全局数据区,每个线程只有自己的栈是独立的),所以全局缓冲区不是技术上的必需,更多是代码写法上的简化:

  • 初学者写代码时,用全局变量可以避免在多个线程函数之间传递结构体指针,减少指针操作的复杂度;
  • 早期的示例代码为了降低理解门槛,会用全局变量让逻辑更直观。

但从工程角度,用结构体封装共享数据(比如你的shared_info)并传递给线程,代码的模块化更好、耦合度更低,更容易维护和扩展,比全局变量更优。所以你现在的做法(用结构体传递)是更规范的,没必要改成全局变量。


修正后的代码

你的代码存在几个严重的错误(比如野指针、未定义变量、信号量未释放等),以下是修正后的版本:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
#include <pthread.h> 
#include <stdbool.h>
#include <time.h>

//function declarations
void* producer(void*);
void* consumer(void*);

typedef struct {
    sem_t mtx;
    sem_t empty;
    sem_t full;
    int *buff;
    int buffSize;
    int psTime;
    int csTime;
    // 新增:记录生产者/消费者的当前操作位置(环形缓冲区常用)
    int in;
    int out;
} shared_info;

int main (int argc, char*argv[]) {
    // 修正:给shr分配内存,避免野指针
    shared_info *shr = malloc(sizeof(shared_info));
    if (shr == NULL) {
        fprintf(stderr, "Failed to allocate shared info.\n");
        exit(1);
    }
    pthread_t pro, con;
    
    if( argc != 4 ){
        fprintf(stderr, "Incorrect number of arguments. Usage: ./program <buffSize> <psTime> <csTime>\n");
        exit(1);
    } 
   
    //grabbing input from command line arguments
    shr->buffSize = strtol(argv[1], NULL, 10);
    shr->psTime = strtol(argv[2], NULL, 10);
    shr->csTime = strtol(argv[3], NULL, 10);
    shr->in = 0;
    shr->out = 0;

    shr->buff = malloc(shr->buffSize * sizeof(int));
    if (shr->buff == NULL)
    {
        fprintf(stderr, "Memory allocation failed for buffer.\n");
        free(shr);
        return -1;
    }
    // 删掉无效代码:shr->buff[shr->buffSize];

    // 修正:printf里的变量需用shr->前缀
    printf("buffSize: %d psTime:%d csTime: %d\n", shr->buffSize, shr->psTime, shr->csTime);

    // 初始化信号量,第二个参数为0表示线程间共享
    sem_init(&shr->mtx, 0, 1);
    sem_init(&shr->full, 0, 0);
    sem_init(&shr->empty, 0, shr->buffSize);

    // 初始化随机数种子
    srand(time(NULL));

    pthread_create(&pro, NULL, producer, shr);
    sleep(1);
    pthread_create(&con, NULL, consumer, shr);

    pthread_join(pro, NULL);
    pthread_join(con, NULL);

    printf("Main thread done.\n");
    sem_destroy(&shr->mtx);
    sem_destroy(&shr->empty);
    sem_destroy(&shr->full);
    // 释放内存
    free(shr->buff);
    free(shr);

    return 0;
}

//producer thread 
void *producer(void * arg){
    // 修正:将参数转换为正确的结构体类型
    shared_info *shr = (shared_info*)arg;
    while( true){
        sem_wait(&shr->empty);
        sem_wait(&shr->mtx);
        
        // 生产随机整数(900-1000)
        int rand1 = rand()%101 + 900;
        shr->buff[shr->in] = rand1;
        printf("Produced: %d, stored at position %d\n", rand1, shr->in);
        shr->in = (shr->in + 1) % shr->buffSize;
        
        sem_post(&shr->mtx);
        sem_post(&shr->full);
        
        // 模拟生产时间
        sleep(shr->psTime);
    }
    return NULL;
}

//Consumer thread
void *consumer(void * arg){
    shared_info *shr = (shared_info*)arg;
    while( true){
        sem_wait(&shr->full);
        sem_wait(&shr->mtx);
        
        int val = shr->buff[shr->out];
        printf("Consumed: %d, from position %d\n", val, shr->out);
        shr->out = (shr->out + 1) % shr->buffSize;
        
        sem_post(&shr->mtx);
        sem_post(&shr->empty);
        
        // 模拟消费时间
        sleep(shr->csTime);
    }
    return NULL;
} 

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 16:21:00