0

我正在尝试实现一个程序,该程序使用线程从文件中读取数据并写入任意大小的缓冲区,而另外两个线程从该缓冲区读取信息。一切正常,除了当我指定缓冲区大小为 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*));
4

1 回答 1

1

没有单步执行您的代码,但您正在编写一个终止 NUL'\0'字节,这将占用整个 1 字节缓冲区。写入者永远等待缓冲区中的空间。

while ((b->writepos + 1) % numlines == b->readpos) { /* always satisfied */
于 2012-04-05T01:40:45.700 回答