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

条件变量与信号量搭配顺序及多消费者生产者同步实现方法

条件变量与信号量搭配使用的调用规则和触发场景

调用顺序

  • 信号量作为消费准入门槛时,优先操作信号量,再处理需要互斥保护的条件变量逻辑
  • 生产端:完成资源准备后,先操作信号量给消费端放开准入权限,再持有互斥锁等待条件变量的完成通知
  • 消费端:先申请信号量获得准入权限,完成资源消费后,再持有互斥锁修改共享计数、触发条件变量通知

触发场景

  • 信号量触发:仅用于控制消费准入,资源未就绪时信号量值为0,所有消费者调用sem_wait直接阻塞;资源就绪后生产端调用对应次数的sem_post,逐个唤醒等待的消费者
  • 条件变量触发:仅用于通知生产端所有消费已完成,每次消费者完成消费后修改计数,当计数达到总消费者数时,调用条件变量通知接口唤醒生产端
你的生产者消费者需求实现方案

首先纠正一个认知误区:POSIX信号量是计数型信号量,不是只能取0/1的二值信号量,你只要初始化时把信号量的初始值设为0,每次生产完调用3次sem_post后信号量值会变成3,刚好允许3个消费者各执行一次sem_wait通过,完全可以实现一次性放开所有消费者读取权限的需求,你原本的信号量用法思路是正确的。

另外你提到不想在消费者逻辑加互斥锁,这个需要调整:共享计数器counter需要被多个消费者修改,自增操作本身不是原子操作,多线程同时修改会出现计数丢失问题,不过互斥锁只会在修改counter的极短时间持有,读消息的逻辑完全不需要加锁,不会影响消费的并发效率。

全局变量定义

#define CONSUMER_CNT 3 // 总消费者数量
int message; // 生产者生成的消息
int counter = 0; // 已完成消费的消费者计数
pthread_mutex_t guard_cv = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond_all_read = PTHREAD_COND_INITIALIZER;
sem_t sem_ready_to_read; // 初始化时设置初始值为0:sem_init(&sem_ready_to_read, 0, 0);

修正后的生产者代码

void *Producer(void *unused)
{   
    while (1)
    {
        /* 生产消息 */
        message = rand () % 100;
        printf("生产者生成消息:%d\n", message);
                
        // 给信号量加3,放开3个消费者的准入权限
        for(int i=0; i<CONSUMER_CNT; i++) {
            sem_post(&sem_ready_to_read);
        }
        
        // 持有互斥锁等待所有消费者消费完成
        pthread_mutex_lock(&guard_cv);
        while (counter != CONSUMER_CNT)
        {
            pthread_cond_wait(&cond_all_read, &guard_cv);
        }
        // 本轮消费完成,重置计数器供下一轮使用
        counter = 0;
        pthread_mutex_unlock(&guard_cv);
    }
    return NULL;
}

消费者代码

void *Consumer(void *arg)
{
    int id = *(int*)arg; // 传入的消费者编号
    while(1) {
        // 申请信号量,消息未就绪时会阻塞在这里
        sem_wait(&sem_ready_to_read);

        // 读取消费消息,仅读操作不需要加锁
        printf("消费者%d读取到消息:%d\n", id, message);

        // 修改共享计数器必须加锁保护
        pthread_mutex_lock(&guard_cv);
        counter++;
        // 所有消费者都读完后通知生产者
        if(counter == CONSUMER_CNT) {
            pthread_cond_signal(&cond_all_read);
        }
        pthread_mutex_unlock(&guard_cv);
    }
    return NULL;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.12 18:54:03