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

生产者-消费者计数器代码出现异常输出问题求助

生产者-消费者交替计数器逻辑问题

我用生产者-消费者模式实现了一个交替运行的计数器,预期计数从0到10共打印10次。但运行时每次计数打印之间会出现大量锁、解锁及信号相关的打印信息,怀疑代码逻辑有问题。

按照预期,生产者和消费者的每次迭代是否应该仅各执行一次锁、解锁和信号操作?

运行输出示例

myCount: 6 -> 7
Producer: signaling myCond1
Producer: waiting on myCond2
CONSUMER: myMutex locked
CONSUMER: signaling myCond2
CONSUMER: myMutex unlocked
Producer: myMutex unlocked
Producer: myMutex locked
CONSUMER: myMutex locked
CONSUMER: signaling myCond2
CONSUMER: myMutex unlocked
myCount: 7 -> 8
Producer: signaling myCond1
Producer: waiting on myCond2
CONSUMER: myMutex locked
CONSUMER: signaling myCond2
CONSUMER: myMutex unlocked
Producer: myMutex unlocked
Producer: myMutex locked
CONSUMER: myMutex locked
CONSUMER: signaling myCond2
CONSUMER: myMutex unlocked
myCount: 8 -> 9
Producer: signaling myCond1
Producer: waiting on myCond2
CONSUMER: myMutex locked
CONSUMER: signaling myCond2
CONSUMER: myMutex unlocked
Producer: myMutex unlocked
Producer: myMutex locked
CONSUMER: myMutex locked
CONSUMER: signaling myCond2
CONSUMER: myMutex unlocked
myCount: 9 -> 10
Producer: signaling myCond1
Producer: waiting on myCond2
CONSUMER: myMutex locked
CONSUMER: signaling myCond2
Producer: myMutex unlocked
Producer: myMutex locked
PROGRAM END

代码实现

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

// Global variables
pthread_mutex_t myMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t myCond1 = PTHREAD_COND_INITIALIZER;
pthread_cond_t myCond2 = PTHREAD_COND_INITIALIZER;
int myCount = 0;

// Function prototypes
void* producerThread(void* arg);
void* consumerThread(void* arg);

int main() {
    // Create consumer thread
    pthread_t consumer;
    printf("PROGRAM START\n");

    if (pthread_create(&consumer, NULL, consumerThread, NULL) != 0) {
        perror("Error creating consumer thread");
        exit(EXIT_FAILURE);
    }

    // Run the producer thread
    producerThread(NULL);

    // Wait for the consumer thread to finish
    pthread_join(consumer, NULL);

    printf("PROGRAM END\n");

    return 0;
}

void* producerThread(void* arg) {
    while (1) {
        printf("Producer: myMutex locked\n");
        pthread_mutex_lock(&myMutex);
        
        if (myCount >= 10) {
            pthread_mutex_unlock(&myMutex);
            break;  // Terminate the program when myCount reaches 10
        }

        myCount++;
        printf("myCount: %d -> %d\n", myCount - 1, myCount);

        // Signal the consumer that a new value is available
        printf("Producer: signaling myCond1\n");
        pthread_cond_signal(&myCond1);

        printf("Producer: waiting on myCond2\n");
        pthread_cond_wait(&myCond2, &myMutex);

        pthread_mutex_unlock(&myMutex);
        printf("Producer: myMutex unlocked\n");
    }

    return NULL;
}

void* consumerThread(void* arg) {
    printf("CONSUMER THREAD CREATED\n");

    while (1) {
        pthread_mutex_lock(&myMutex);
        printf("CONSUMER: myMutex locked\n");

        // Wait for the producer to signal that a new value is available
        while (myCount == 0) {
            printf("CONSUMER: waiting on myCond1\n");
            pthread_cond_wait(&myCond1, &myMutex);
        }

        // Signal the producer that the value has been consumed
        printf("CONSUMER: signaling myCond2\n");
        pthread_cond_signal(&myCond2);

        if (myCount >= 10) {
            pthread_mutex_unlock(&myMutex);
            break;  // Terminate the program when myCount reaches 0
        }
        
        pthread_mutex_unlock(&myMutex);
        printf("CONSUMER: myMutex unlocked\n");
    }

    return NULL;
}

问题分析与修复

核心问题

  1. 锁操作顺序错误:生产者先打印锁已获取的信息,再实际调用pthread_mutex_lock,导致打印状态与实际锁状态不符;且生产者在pthread_cond_wait返回后直接解锁,下一次循环立刻重新加锁,触发无意义的线程切换。
  2. 消费者循环逻辑冗余:消费者每次循环无条件加锁,即使myCount已达10,仍会重复执行加锁、发信号、解锁操作,直到生产者退出。
  3. 终止逻辑混乱:消费者注释标注"计数到0时退出",但实际判断条件是myCount >=10,逻辑不一致。

预期正确流程

每次迭代应严格交替:

  • 生产者:加锁 → 计数递增 → 通知消费者 → 等待消费者确认 → 解锁
  • 消费者:加锁 → 等待生产者通知 → 通知生产者 → 解锁
    两者各执行一次锁、解锁、信号操作。

修复后的代码

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

pthread_mutex_t myMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t myCond1 = PTHREAD_COND_INITIALIZER; // 生产者通知消费者
pthread_cond_t myCond2 = PTHREAD_COND_INITIALIZER; // 消费者通知生产者
int myCount = 0;
int done = 0; // 标记生产是否结束

void* producerThread(void* arg) {
    while (1) {
        pthread_mutex_lock(&myMutex);
        
        if (myCount >= 10) {
            done = 1;
            pthread_cond_signal(&myCond1); // 通知消费者退出
            pthread_mutex_unlock(&myMutex);
            break;
        }

        myCount++;
        printf("myCount: %d -> %d\n", myCount - 1, myCount);

        pthread_cond_signal(&myCond1); // 通知消费者处理新计数
        printf("Producer: signaling myCond1, waiting on myCond2\n");
        pthread_cond_wait(&myCond2, &myMutex); // 等待消费者确认

        pthread_mutex_unlock(&myMutex);
    }
    printf("Producer thread exit\n");
    return NULL;
}

void* consumerThread(void* arg) {
    printf("CONSUMER THREAD CREATED\n");

    while (1) {
        pthread_mutex_lock(&myMutex);

        // 仅在无新计数且未结束时等待
        while (myCount == 0 && !done) {
            printf("CONSUMER: waiting on myCond1\n");
            pthread_cond_wait(&myCond1, &myMutex);
        }

        // 检测到结束信号则退出
        if (done) {
            pthread_mutex_unlock(&myMutex);
            break;
        }

        printf("CONSUMER: signaling myCond2\n");
        pthread_cond_signal(&myCond2); // 通知生产者继续生产

        pthread_mutex_unlock(&myMutex);
    }
    printf("Consumer thread exit\n");
    return NULL;
}

int main() {
    pthread_t consumer;
    printf("PROGRAM START\n");

    if (pthread_create(&consumer, NULL, consumerThread, NULL) != 0) {
        perror("Error creating consumer thread");
        exit(EXIT_FAILURE);
    }

    producerThread(NULL);

    pthread_join(consumer, NULL);

    printf("PROGRAM END\n");

    return 0;
}

修复说明

  1. 修正锁操作顺序:生产者先加锁再打印状态,确保信息准确。
  2. 新增结束标记done:明确告知消费者生产已完成,避免无意义循环。
  3. 优化消费者等待逻辑:仅在需要时等待,减少冗余的锁操作。
  4. 对齐终止逻辑:生产者完成后主动通知消费者退出,避免线程僵死。

修复后,每次计数变化只会对应一次生产者和消费者的锁、解锁、信号操作,不会出现多余的打印信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 12:27:07