实施生产者/消费者沟通

时间:2015-03-06 02:21:11

标签: c unix pthreads buffer producer-consumer

我试图通过有限的缓冲区实现生产者/消费者的沟通,使用信号量和已经在C中实现的锁。我需要有生产者的地方" hello world"到一个5字节的缓冲区,一次一个字符。如果缓冲区已满,则生产者需要阻止。我正在努力弄清楚如何将字符串放在缓冲区上。以下是我到目前为止的情况:

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

#define BUF_SIZE 5

// the buffer works like a stack for
// the sake of simplicity, if needed
// we may implement a queue
 typedef struct {
    int buf[BUF_SIZE]; // the buffer
    size_t len; // number of items in the buffer
    pthread_mutex_t mutex; // needed to add/remove data from the buffer
    pthread_cond_t can_produce; // signaled when items are removed
    pthread_cond_t can_consume; // signaled when items are added
 } buffer_t;

// produce random numbers
void* producer(void *arg) {
    buffer_t *buffer = (buffer_t*)arg;

while(1) {
 #ifdef UNDERFLOW
    // used to show that if the producer is somewhat "slow"
    // the consumer will not fail (i.e. it'll just wait
    // for new items to consume)
    sleep(rand() % 3);
 #endif

    pthread_mutex_lock(&buffer->mutex);

    if(buffer->len == BUF_SIZE) { // full
        // wait until some elements are consumed
        pthread_cond_wait(&buffer->can_produce, &buffer->mutex);
    }

    // in real life it may be some data fetched from
    // sensors, the web, or just some I/O
    int t = rand();
    printf("Produced: %d\n", t);

    // append data to the buffer
    buffer->buf[buffer->len] = t;
    ++buffer->len;

    // signal the fact that new items may be consumed
    pthread_cond_signal(&buffer->can_consume);
    pthread_mutex_unlock(&buffer->mutex);
}

// never reached
return NULL;
}

// consume random numbers
void* consumer(void *arg) {
buffer_t *buffer = (buffer_t*)arg;

while(1) {
#ifdef OVERFLOW
    // show that the buffer won't overflow if the consumer
    // is slow (i.e. the producer will wait)
    sleep(rand() % 3);
 #endif
    pthread_mutex_lock(&buffer->mutex);

    if(buffer->len == 0) { // empty
        // wait for new items to be appended to the buffer
        pthread_cond_wait(&buffer->can_consume, &buffer->mutex);
    }

    // grab data
    --buffer->len;
    printf("Consumed: %d\n", buffer->buf[buffer->len]);

    // signal the fact that new items may be produced
    pthread_cond_signal(&buffer->can_produce);
    pthread_mutex_unlock(&buffer->mutex);
}

// never reached
return NULL;
}

int main(int argc, char *argv[]) {
buffer_t buffer = {
    .len = 0,
    .mutex = PTHREAD_MUTEX_INITIALIZER,
    .can_produce = PTHREAD_COND_INITIALIZER,
    .can_consume = PTHREAD_COND_INITIALIZER
};

pthread_t prod, cons;
pthread_create(&prod, NULL, producer, (void*)&buffer);
pthread_create(&cons, NULL, consumer, (void*)&buffer);

pthread_join(prod, NULL); // will wait forever
pthread_join(cons, NULL);

return 0;
}

1 个答案:

答案 0 :(得分:0)

一个堆栈是一个Last in,First out。不是你想要的。

我强烈要实现一个带有头尾指针的循环缓冲区。

然后使用互斥锁(不需要信号量)来锁定关键代码。

(生产者的关键代码是添加/尝试添加char的地方)

(消费者的关键代码是删除/尝试删除字符的位置)

互斥是两个关键变量&#39; head&#39;并且&#39;尾巴&#39;很稳定 任何一个进程都在访问循环队列。