消费者/生产者多线程同步错误

时间:2016-10-27 14:51:38

标签: c multithreading synchronization semaphore

我编写了一个由四个线程组成的程序。第一个用于初始化其他项,第二个用于生成项并将它们添加到缓冲区,第三个用于将项添加到另一个缓冲区,第四个用于从任一缓冲区中使用项。我的问题是第四个线程在写入之前从缓冲区槽读取。我已经设置信号量以尝试同步,但它们没有像我期望的那样执行。

我在保持错误的同时简化了我的代码:

#include <stdlib.h>
#include <stdio.h>
#include <semaphore.h>
#include <pthread.h>
#include <sys/types.h>

/* thread routines */
void* threadA ();
void* threadB ();
void* threadC ();

/* thread ids */
pthread_t tid[3];

/* semaphores */
sem_t sA;
sem_t sB;
sem_t a_empty;
sem_t b_empty;
sem_t both_full;
sem_t mutex;

/* buffers */
int buffA[20];
int buffB[40];

/* int a for tracking buffA */
int a = 0;

int main()
{

/* initializing semaphores */
  sem_init (&a_empty, 20, 1);
  sem_init (&b_empty, 40, 1);
  sem_init (&both_full, 0, 1);
  sem_init (&mutex, 1, 1);
  sem_init (&sA, 0, 1);
  sem_init (&sB, 0, 1);

/* creating threads */
  pthread_create(&tid[0], NULL, threadA, NULL);
  pthread_create(&tid[1], NULL, threadB, NULL);
  pthread_create(&tid[2], NULL, threadC, NULL);

/* waiting on threads */
  pthread_join(tid[0], NULL);
  pthread_join(tid[1], NULL);
  pthread_join(tid[2], NULL);
}

/* Producer */
void* threadA ()
{
 int i;
 int inA = 0;

/* two process two way synch*/
 sem_post(&sB);
 sem_wait(&sA);

 for (i = 1; i <= 300; i++)
 {

/* adding item to buffer */
   sem_wait(&a_empty);
   buffA[inA] = i;

/* incrementing a */
   sem_wait(&mutex);
   a = a + 1;
   sem_post(&mutex);

/* signaling full buffer */
   sem_post(&both_full);

/* updating inA */
   inA = (inA + 1) % 20;

 }

 pthread_exit(NULL);
}

/* Producer */
void* threadB ()
{
 int i, j, inB;
 inB = 0;

/* two process two way synch*/
 sem_post(&sA);
 sem_wait(&sB);

 for(i = 1; i <= 400; i++)
 {

/* producing item. */ 
   sem_wait(&b_empty);
   buffB[inB] = i;

   sem_post(&both_full);

   inB = (inB + 1) % 40;
 }

 pthread_exit(NULL);
}

/* Consumer */
void* threadC ()
{
 int i, j, outA, outB, bsum, asum;
 outA = 0;
 outB = 0;
 asum = 0;
 bsum = 0;
 int prod_a;
 int prod_b;

 for(i = 0; i < 700; i++)
 {

  sem_wait(&both_full);
  if (a > 0) {
    asum++;
    prod_a = buffA[outA];
    outA = (outA + 1) % 20;
    sem_wait(&mutex);
    a = a - 1;
    sem_post(&mutex);
    sem_post(&a_empty);

    printf("A-%d\t", prod_a);
  } 
  else {
    bsum++;

    prod_b = buffB[outB];
    outB = (outB + 1) % 40;  
    sem_post(&b_empty);

    printf("B-%d\t", prod_b);
  }
 }

 printf("\n a=%d b=%d \n", asum, bsum);
 pthread_exit(NULL);
}

我的问题似乎是threadC()中的else语句在不应该执行时执行。我无法确定导致这种情况的原因。

编辑:我正在使用gcc file.c -o file.o -lrt -lpthread来编译

1 个答案:

答案 0 :(得分:1)

信号量both_full应使用值0进行初始化:

sem_init (&both_full, 0, 0);

通常,outB应始终等于或小于inB。但是,如果将both_full初始化为1,那么threadC()中的else语句会在某个时刻运行且没有可用输入,从而允许outB增加到inB+1。因此,对于前40次,您可能会看到零(静态缓冲区在程序启动时归零),此后您可能会看到旧值,如B-51 B-52 B-13 B-54 < / p>