我正在尝试实现一个程序,该程序使用线程从文件中读取数据并写入任意大小的缓冲区,而另外两个线程从该缓冲区读取信息。一切正常,除了当我指定缓冲区大小为 1 时。当我这样做时,一切都锁定了。我或多或少地从这里改编了经典的“消费者/生产者”示例这是我的代码:
我正在使用的结构:
struct prodcons {
char** buffer; pthread_mutex_t lock;
pthread_cond_t notempty; pthread_cond_t notfull;
int readpos, writepos, finished;
};
我的“添加到缓冲区”线程
static void buf_add(struct prodcons *b, char* data) {
/* Add the data after locking the buffer */
pthread_mutex_lock(&b-> lock);
printf("Reader adding %s\n", data);
int err;
/*Wait until buffer is not full*/
while ((b->writepos + 1) % numlines == b->readpos) {
err = pthread_cond_wait(&b->notfull, &b->lock);
if (err != 0) { fprintf(stderr, "cond wait");}
}
/* Needed to stop writes */
if (data != NULL) {
b->buffer[b->writepos] = strdup(data);
} else {
//fprintf(stderr, "End of file reached, adding NULL\n");
b->buffer[b->writepos] = NULL;
}
/* Increments the writing position */
(*b).writepos++;
if ((*b).writepos >= numlines) {
printf("Resetting write position\n");
(*b).writepos = 0;
}
/* Unlock */
pthread_cond_signal(&b->notempty);
pthread_mutex_unlock(&b->lock);
}
这是输出的样子:
Reader adding 64.233.173.85
然后它就挂了。很明显,它永远不会超出第一个 while 循环。它适用于任何其他尺寸,但不适用于 1。对此实施修复的最佳方法是什么?如果这有帮助,这是我的“从缓冲区获取”方法。
static void *read_from_buffer(struct prodcons *b) {
pthread_mutex_lock(&b -> lock);
/* We have to wait for the buffer to have something in it */
while ((*b).writepos == (*b).readpos) {
pthread_cond_wait(&b->notempty, &b->lock);
}
/* Set the thread delay */
thread_delay.tv_sec = threaddelay / 100000;
thread_delay.tv_nsec = 1000*threaddelay%100000;
char *t = NULL;
/* Read the data and advance the reader pointer */
if ((*b).buffer[(*b).readpos] != NULL) {
t = (char*)malloc(strlen ((*b).buffer[(*b).readpos] ) + 1);
strcpy(t, (*b).buffer[(*b).readpos]);
printf("Consumer %u reading from buffer: got %s\n", (unsigned int)pthread_self(), t);
/*At this point, we should probably check is FQDN*/
if (strcmp(t, "-1") == 0) {
(*b).finished = 1;
} else {
nanosleep(&thread_delay, &thread_delay_rem);
check_cache(t, &cache);
}
}
/* We have to adjust the reading position */
(*b).readpos++;
if ( (*b).readpos >= numlines) {
(*b).readpos = 0;
}
/*Need to signal and unlock */
pthread_cond_signal (&b->notfull);
pthread_mutex_unlock(&b->lock);
return t;
}
我确信有一个相当简单的解决方法来处理这种边缘情况,但我似乎无法弄清楚。我们欢迎所有的建议!
编辑:我也像这样初始化我的缓冲区:
static void init(struct prodcons *temp) {
(*temp).buffer = (char**)malloc(numlines * sizeof(char*));