使用条件变量的正确方法是什么?

问题描述 投票:0回答:1

我的作业提供了运行时使用大量 CPU 的代码。目标是通过在生产者消费者问题中实施条件变量来减少该数量。

我按照我最好的理解提供的说明进行操作,在互斥体解锁之前在生产者端添加 wait() 函数,然后从 if-else 语句的 else 部分发送信号。

            // if buffer is full, release mutex lock and check again
            if (shared_count == NITEMS){

                 // wait when full
                pthread_cond_wait(&cond1, &mutex);
                pthread_mutex_unlock(&mutex);

            }
            else{
                //signal
                pthread_cond_signal(&cond1);
                break;
            }

我在消费者方面也做了同样的事情。

问题是我的整体代码不再提供任何输出。

我在下面包含了完整的代码,以防有帮助

/* minor3.c - using producer-consumer paradigm. */

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

#define NITEMS 10       // number of items in shared buffer

// shared variables
char shared_buffer[NITEMS]; // echo buffer
int shared_count;       // item count

pthread_mutex_t mutex;      // pthread mutex
unsigned int prod_index = 0;    // producer index into shared buffer
unsigned int cons_index = 0;    // consumer index into shard buffer

// function prototypes
void * producer(void *arg);
void * consumer(void *arg);

// Consumer variables
pthread_cond_t cond1 = PTHREAD_COND_INITIALIZER;
pthread_cond_t cond2 = PTHREAD_COND_INITIALIZER;

int main()
{
    pthread_t prod_tid, cons_tid1, cons_tid2;

    // initialize pthread variables
    pthread_mutex_init(&mutex, NULL);

    // initialize condition variables
    pthread_cond_init(&cond1, NULL);
    pthread_cond_init(&cond2, NULL);

    // start producer thread
    pthread_create(&prod_tid, NULL, producer, NULL);

    // start consumer threads
    pthread_create(&cons_tid1, NULL, consumer, NULL);
    pthread_create(&cons_tid2, NULL, consumer, NULL);

    // wait for threads to finish
    pthread_join(prod_tid, NULL);
    pthread_join(cons_tid1, NULL);
    pthread_join(cons_tid2, NULL);

    // clean up
    pthread_mutex_destroy(&mutex);

    pthread_cond_destroy(&cond1);
    pthread_cond_destroy(&cond2);

    return 0;
}

// producer thread executes this function
void * producer(void *arg)
{
    char key;

    printf("Enter text for producer to read and consumer to print, use Ctrl-C to exit.\n\n");

    // this loop has the producer read data in from stdin and place the read data on the shared buffer
    while (1)
    {
        // read input key
        scanf("%c", &key);

        // this loop is used to poll the shared buffer to see if it is full:
        // -- if full, unlock and loop again to keep polling
        // -- if not full, keep locked and proceed to place character on shared buffer
        while (1)
        {
            // acquire mutex lock
            pthread_mutex_lock(&mutex);

            // if buffer is full, release mutex lock and check again
            if (shared_count == NITEMS){

                 // wait when full
                pthread_cond_wait(&cond1, &mutex);
                pthread_mutex_unlock(&mutex);

            }
            else{
                //signal
                pthread_cond_signal(&cond1);
                break;
            }

        }

        // store key in shared buffer
        shared_buffer[prod_index] = key;

        // update shared count variable
        shared_count++;

        // update producer index
        if (prod_index == NITEMS - 1)
            prod_index = 0;
        else
            prod_index++;

        // release mutex lock
        pthread_mutex_unlock(&mutex); 
    }

    return NULL;
}

// consumer thread executes this function
void * consumer(void *arg)
{
    char key;

    long unsigned int id = (long unsigned int)pthread_self();

    // this loop has the consumer get data from the shared buffer and print to stdout
    while (1)
    {
        // this loop is used to poll the shared buffer to see if it is empty:
        // -- if empty, unlock and loop again to keep polling
        // -- if not empty, keep locked and proceed to get character from shared buffer
        while (1)
        {
            // acquire mutex lock
            pthread_mutex_lock(&mutex);

            // if buffer is empty, release mutex lock and check again
            if (shared_count == 0){
                
                pthread_cond_wait(&cond2, &mutex);
                pthread_mutex_unlock(&mutex);

                }
            else{

                pthread_cond_signal(&cond2);
                break;

                }
        }

        // read key from shared buffer
        key = shared_buffer[cons_index];

        // echo key
        printf("consumer %lu: %c\n", (long unsigned int) id, key);

        // update shared count variable
        shared_count--;

        // update consumer index
        if (cons_index == NITEMS - 1)
            cons_index = 0;
        else
            cons_index++;

        // release mutex lock
        pthread_mutex_unlock(&mutex);
    }

    return NULL;
}



c mutex race-condition producer-consumer condition-variable
1个回答
0
投票

你有两个错误。

首先,你永远不会将

shared_count
设置为零。您可以递增、递减并测试它。但你永远不会初始化它。

其次,消费者发出消费者等待的条件变量信号,反之亦然。您需要消费者向生产者发出信号,反之亦然!

最后,虽然这不是一个错误,但您的循环不必要地解锁互斥体,只是为了在下一次迭代时立即再次锁定它。在内循环之外解锁互斥体可能更有意义。

© www.soinside.com 2019 - 2024. All rights reserved.