【问题标题】:producer consumer synchronizing11生产者消费者同步11
【发布时间】:2014-07-26 12:39:06
【问题描述】:
#include <stdio.h>
#include <pthread.h>
#define MAX 10                                  /* maximum iterations */
int number;                                     /* the resource */
pthread_mutex_t mu= PTHREAD_MUTEX_INITIALIZER;  /* to protect the resource*/
/*
    Condition variable to signal consumer that a new number is available for
    consumption.
*/
pthread_cond_t sig_consumer= PTHREAD_COND_INITIALIZER;
/*
      Condition variable to signal the producer that
      (a) the new number has been consumed,
      (b) generate another one.
*/
pthread_cond_t sig_producer= PTHREAD_COND_INITIALIZER;
void *consumer(void *dummy)
{
      int printed= 0;
      printf("Consumer : \"Hello I am consumer #%ld. Ready to consume numbers"
             " now\"\n", pthread_self());

      while (1)
      {
         pthread_mutex_lock(&mu);
         /* Signal the producer that the consumer is ready. */
         pthread_cond_signal(&sig_producer);
         /* Wait for a new number. */
         pthread_cond_wait(&sig_consumer, &mu);
         /* Consume (print) the number. */
         printf("Consumer : %d\n", number);
         /* Unlock the mutex. */
         pthread_mutex_unlock(&mu);

         /*
           If the MAX number was the last consumed number, the consumer should
           stop.
         */
         if (number == MAX)
         {
           printf("Consumer done.. !!\n");
           break;
         }
      }
}
        /**
          @func producer
          This function is responsible for incrementing the number and signalling the
          consumer.
        */
void *producer(void *dummy)
{
      printf("Producer : \"Hello I am producer #%ld. Ready to produce numbers"
             " now\"\n", pthread_self());
      while (1)
      {
            pthread_mutex_lock(&mu);
            number ++;
            printf("Producer : %d\n", number);
            /*
              Signal the consumer that a new number has been generated for its
              consumption.
            */
            pthread_cond_signal(&sig_consumer);
            /*
              Now wait for consumer to confirm. Note, expect no confirmation for
              consumption of MAX from consumer.
            */
            if (number != MAX)
              pthread_cond_wait(&sig_producer, &mu);

            /* Unlock the mutex. */
            pthread_mutex_unlock(&mu);

            /* Stop if MAX has been produced. */
            if (number == MAX)
            {
              printf("Producer done.. !!\n");
              break;
            }
      }
}

void main()
{
      int rc, i;
      pthread_t t[2];
      number= 0;
      /* Create consumer & producer threads. */
      if ((rc= pthread_create(&t[0], NULL, consumer, NULL)))
        printf("Error creating the consumer thread..\n");
      if ((rc= pthread_create(&t[1], NULL, producer, NULL)))
        printf("Error creating the producer thread..\n");

      /* Wait for consumer/producer to exit. */
      for (i= 0; i < 2; i ++)
        pthread_join(t[i], NULL);

      printf("Done..\n");
} 

问题:如果消费者线程在生产者线程之前启动,那么程序会提供预期的结果,但是如果生产者先启动,那么消费者将从第2个开始消费;消费者无法消费1号。如何在生产者线程先启动的情况下纠正程序,而不引入任何额外的变量或睡眠?

【问题讨论】:

  • 这不是你使用pthread_cond_wait的方式。您需要在循环中调用它(它可能会自发返回),并且每次循环都需要测试,在锁定的情况下,您实际上是否能够继续。
  • pthread_cond_wait for 2 threads 的可能重复项
  • 请注意,当您使用 POSIX 线程时,void main() 是不允许的。它只在 Windows 系统上是允许的,即使在那里也是一种异常(但有记录的异常)。
  • @AlanStokes,您的示例包含另外一个名为 enum { STATE_A, STATE_B } state = STATE_A; 的全局变量。我的意图是没有任何额外的变量如何克服我的问题。
  • 你不能。该问题的答案以及下面的答案解释了这一点。

标签: c pthreads


【解决方案1】:

pthread_cond_t 的问题在于它的名称。尽管名义上是一个“条件”,但它没有状态...特别是,它根本不记得它已经发出信号——如果你认为它可以计算它已经发出了多少次发出信号,你会感到失望(因为你需要一个信号量)。换句话说,如果在发出信号时没有 pthread 等待某个条件,则该信号无效并被遗忘。

“条件”最好被认为是“等待队列”,其中 pthread 等待某些状态被更新。所以通常你有一些受互斥锁保护的状态。如果状态不是 pthread 继续所需的状态,则 pthread 等待“条件”。当状态更新时,可以发出“条件”的信号。当服务员醒来时,它必须检查状态,并决定现在是否一切都准备好继续。

当有两个或多个 pthreads 等待时,标准允许pthread_cond_signal() 唤醒一个、两个或更多或所有等待者。互斥锁确保等待者对状态的访问是序列化的,但等待者不能(通常,特别是出于这个原因)假设状态自信号以来没有改变。所以,写服务员是很常见的:

pthread_mutex_lock(&mutex) ;
....
while(...what we need to continue...)
  pthread_cond_wait(&cond, &mutex) ;
....
pthread_mutex_unlock(&mutex) ;

这反映了状态的重要性,以及“条件”的贡献有多大。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-13
    • 2018-01-07
    • 1970-01-01
    • 2015-12-14
    • 2018-10-16
    相关资源
    最近更新 更多