生产者/消费者似乎是在僵局时,缓冲区是不是从生产者输入较小 [英] Producer/consumer seems to be in deadlock when buffer is smaller than input from producer

查看:249
本文介绍了生产者/消费者似乎是在僵局时,缓冲区是不是从生产者输入较小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我做了一个循环缓冲区与多个客户端写入(在我希望他们能写不同大小的消息结束)到缓冲区中。服务器读取出来。它是基于在code在消费者/生产者问题:

I made a circular buffer with multiple clients writing (in the end I want them to write messages of different size) into a buffer. The server reads them out. It's based on the code in a consumer/producer problem:

#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>

#define BUFFER_SIZE 10

struct cBuf{
    char    *buf;  
    int     size; 
    int     start; 
    int     end;    
    pthread_mutex_t mutex;
    pthread_cond_t  buffer_full;
    pthread_cond_t  buffer_empty;
};

struct cBuf cb;

void buf_Init(struct cBuf *cb, int size) {
    int i;
    cb->size  = size + 1; 
    cb->start = 0;
    cb->end   = 0; 
    cb->buf = (char *)calloc(cb->size, sizeof(char));   
}
void buf_Free(struct cBuf *cb) {
    free(cb->buf);
}
int buf_IsFull(struct cBuf *cb) {
    return (cb->end + 1) % cb->size == cb->start; 
}
int buf_IsEmpty(struct cBuf *cb) {
    return cb->end == cb->start; 
}

int buf_Insert(struct cBuf *cb, char *elem) {

    int i,j;
    pthread_mutex_lock(&(cb->mutex));
    for (i=0; i < strlen(elem); ++ i){
        if (buf_IsFull(cb)==1) printf("\nProducer (buf_Insert) is waiting ");
        while(buf_IsFull(cb)){                      
            pthread_cond_wait(&(cb->buffer_empty),&(cb->mutex));
        } 

        cb->buf[cb->end] = elem[i]; 
        cb->end = (cb->end + 1) % cb->size;     
        printf("%c-",elem[i]);
    }

    pthread_cond_signal(&(cb->buffer_full));
    pthread_mutex_unlock(&(cb->mutex));     
    return 0;       
}

int buf_Read(struct cBuf *cb, char *out) {
    int i,j;
    pthread_mutex_lock(&(cb->mutex));
    if (buf_IsEmpty(cb))printf("\nConsumer (buf_Read) is waiting ");
    while(buf_IsEmpty(cb)){
        pthread_cond_wait(&(cb->buffer_full),&(cb->mutex));
    }

    for (i=0;i<BUFFER_SIZE-1;i++){
        if (cb->start == cb->end) break;

        out[i] = cb->buf[cb->start];
        cb->buf[cb->start] = '_';
        cb->start = (cb->start + 1) % cb->size;

        printf("%c-",out[i]);
    }
    pthread_cond_signal(&(cb->buffer_empty));
    pthread_mutex_unlock(&(cb->mutex)); 
    return 0;
}

void * client(void *cb){
    pthread_detach(pthread_self());

    struct cBuf *myData;
    myData = (struct cBuf*) cb;

    char input[]="Hello World!";

    if (buf_Insert(myData, input)) printf("\n");
    return 0;
}

int main(void) {
    char out[60];
    pthread_t thread;
    int i;

    pthread_cond_init(&(cb.buffer_full),NULL);
    pthread_cond_init(&(cb.buffer_empty),NULL);

    buf_Init(&cb, BUFFER_SIZE);

    for (i = 0; i<1; i++){
            if(pthread_create (&thread,NULL, client, (void *) &cb) !=0){
            #ifdef DEBUG
            printf("\nDEBUG (Main Thread) - Error while creating thread");
            #endif
        } else {
            #ifdef DEBUG
            printf("\nDEBUG (Main Thread) - Thread created");
            #endif
        }
    }

    while (1){
        if (buf_Read(&cb,out)) printf ("succes");
    }

    buf_Free(&cb);
    return 0;
}

当缓冲区比单个客户端的消息做大它主要的工作原理(通过 BUFFER_SIZE 更大,例如,16)。当我使其体积更小,但是,它似乎陷入僵局,甚至大量的研究后,我想不通为什么。当我在调试器中运行code时,code出现失速就行了。

It mostly works when the buffer is bigger than the message of a single client (by making buffer_size bigger, e.g., 16). When I make it smaller, however, it seems to deadlock, and even after a lot of research, I can't figure out why. When I run the code in a debugger, the code appears to stall on the line

pthread_cond_wait(&(cb->buffer_empty),&(cb->mutex));

为什么code失速这里哪能prevent从失速?

Why is the code stalling here and how can I prevent it from stalling?

推荐答案

你说比小消息,奇异?如果缓冲区不够大,存储甚至一个消息,比生产者将停在半路队列写它,从不避开,通知有东西消耗了消费者。

Did you say "smaller than the message", in singular? If the buffer is not big enough to store even one message, than the producer will stop halfway writing it in the queue and never get around to notifying the consumer that it has something to consume.

通过code简要扫描似乎证实了 - 如果不能写,甚至一个消息,你在写作循环块,但没有得到到调用pthread_cond_signal 调用的函数结束,所以你永远通知消费者,并不能释放缓冲区。

Brief scan through the code seems to confirm that -- if even one message can't be written, you block in the writing loop and don't get to the pthread_cond_signal call at the end of the function, so you never notify the consumer and it can't free up the buffer.

此问题是主要的。该消费者可以就消耗的基本单元具有以适合在队列中。可以解决这个问题以两种方式 - 要么确保缓冲器是消息足够大,或使在较小的单元处理该消息并通知消费者(调用pthread_cond_signal )之后的每个单位。

This problem is principal. The elementary unit that the consumer can start consuming has to fit in the queue. You can resolve the problem in two ways -- either make sure the buffer is large enough for the message, or make the message processable in smaller units and notify the consumer (pthread_cond_signal) after each unit.

这篇关于生产者/消费者似乎是在僵局时,缓冲区是不是从生产者输入较小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆