Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/silverlight/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 单一生产者和多消费者_C_Linux_Multithreading_Pthreads_Producer Consumer - Fatal编程技术网

C 单一生产者和多消费者

C 单一生产者和多消费者,c,linux,multithreading,pthreads,producer-consumer,C,Linux,Multithreading,Pthreads,Producer Consumer,我尝试使用这样一种场景:生产者向缓冲区(state.value)生成一个值,多个使用者读取缓冲区并在数组中更新它。下面是代码 #include <pthread.h> #include <stdio.h> #include <stdlib.h> pthread_mutex_t mutex; pthread_cond_t prod, cons; static int count = 0; struct

我尝试使用这样一种场景:生产者向缓冲区(state.value)生成一个值,多个使用者读取缓冲区并在数组中更新它。下面是代码

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


    pthread_mutex_t mutex;
    pthread_cond_t prod, cons;

    static int count = 0;
    struct shared_state{
    int done;
    int value;
    int value_available;
    int *array;
    int j;
    }state;

   void * producer(void *arg){
      int a[] = {12,11,10,9,8,7};
      int size = sizeof(a)/sizeof(a[0]);
      int i = 0;
      while(i<size){
      pthread_mutex_lock(&mutex);
      while(state.value_available)
        pthread_cond_wait(&prod, &mutex);

      state.value = a[i++];
      printf("In producer: %d\n",state.value);
      state.value_available = 1;
      pthread_cond_signal(&cons);
      pthread_mutex_unlock(&mutex);
    }
      state.done = 1;
      count++;
      printf("Producer count: %d\n",count);
      pthread_exit(NULL);
    }


    void * consumer(void *arg){

       while(!(state.done)){
       pthread_mutex_lock(&mutex);
       while(!state.value_available)
       pthread_cond_wait(&cons,&mutex);
       state.array[(state.j)] = state.value;
       printf("In consumer: %d\t%d\n",state.array[state.j], state.j);
       (state.j)++;
       state.value_available = 0;
       pthread_cond_signal(&prod);
       pthread_mutex_unlock(&mutex);
     }
     int i; 
     for(i=0;i<6;i++)
     printf("%d-->",state.array[i]);
     printf("\n");  
     count++;
     printf("Consumer count: %d\n",count);
   }

   int main(void){

     state.done = 0;
     pthread_t pro,con,con2;
     state.value_available = 0;
     state.j = 0;
     state.array = (int *)malloc(sizeof(int)*6);
     pthread_create(&pro, NULL, producer, (void *)NULL);
     pthread_create(&con, NULL, consumer, (void *)NULL);
     pthread_create(&con2, NULL, consumer, (void *)NULL);
     pthread_join(pro,NULL);
     pthread_join(con,NULL);
     pthread_join(con2,NULL);
     pthread_exit(NULL);
     printf("\n");
     return 0;
   }  

首先,无法初始化互斥体和条件变量。因为它们是全局的,所以它们的初始状态并不是因为这个原因而不确定的,但也不一定是有效的。必须使用适当的初始化函数,或使用用于初始化宏的初始化函数。比如说,

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t prod = PTHREAD_COND_INITIALIZER;
pthread_cond_t cons = PTHREAD_COND_INITIALIZER;
你似乎在这个问题上很幸运,但这并不意味着你不应该解决它

第二,不检查函数调用的返回值是否有错误代码。要使代码健壮,您确实必须这样做。错误发生的原因既有代码中断,也有不受控制的运行时问题,如果您认为函数调用总是成功的,那么您迟早会遇到麻烦

但是,您还有一个更大的问题:
pthread\u cond\u signal()
会唤醒一个在给定条件变量上等待的线程(如果确实有线程在等待)。当生产者最后一次向CV发送信号时,两个使用者线程都可能被阻塞。在这种情况下,一个唤醒并执行其处理,但另一个保持阻塞状态。因为使用者在从等待中醒来后会对条件谓词执行正确的检查,所以可以使用
pthread\u cond\u broadcast()
来解决该问题

但这只是解决方案的一半。因为您确实执行了正确的谓词检查,而且因为使用者将更新共享状态,使其自己的谓词在释放互斥之前为false,所以第二个使用者只要从等待中醒来,就会恢复等待。此外,如果不继续轮候,又会怎样呢?它没有可供消费的价值,也没有可供选择的路径

底线:

  • 您的制作人必须向消费者的简历进行广播,而不是向其发出信号,至少在制作完最后一个产品之后
  • 当消费者从等待CV中醒来时,它不仅必须检查值是否可用,还必须检查生产者是否完成。在这两种情况下,它都不能恢复等待,但只有当一个值实际可用时,它才能使用该值

我猜想“第二个”线程正在不确定地等待pthread_cond_wait(&cons,&mutex),我建议使用pthread_cond_timedwait,而不是您真正想要测试所有相关系统调用的结果(这里主要是
pthread_*()
调用)。这是免费调试!函数中:main():由于此行:
pthread_exit(NULL),以下几行:
printf(“\n”)
返回0将永远不会执行。线程:
consumer()
缺少(干净编译和正确执行顺序所必需的)
pthread\u退出(NULL)(void)arg
谢谢John。在结合state.done和broadcast之后,我可以毫不费力地解决它。
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t prod = PTHREAD_COND_INITIALIZER;
pthread_cond_t cons = PTHREAD_COND_INITIALIZER;