C语言 如何确保生产者线程和使用者线程一个接一个地无限运行?



如何确保生产者和消费者函数无限且一个接一个地运行?例如:首先,我希望用户输入数组,然后 consumer 函数打印输入的数组,然后再次要求用户输入数组。

/*  Headers  */

pthread_mutex_t mutex;
pthread_cond_t cond,cond1;
void *producer(void *arg);
void *consumer(void *arg);
static int n;
int consumerFlag[100];
void *producer(void *arg) 
{
pthread_mutex_lock(&mutex);        
while(1)
{
printf("n Enter no of terms");
scanf("%d",&n);
int i; 
printf("n Enter consumer flag array");
for (i = 0; i < n; i++) 
{
scanf(" %d",&consumerFlag[i]);
pthread_mutex_unlock(&mutex);           
}
pthread_cond_signal(&cond);    
usleep(1000);
}

}

void *consumer(void *arg) 
{
int i;
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex); 
printf("nConsumer Function"); 
while(1)
{
printf("nConsumer thread waiting"); 
for (i = 0; i < n; i++) 
{    
printf("nConsumerFlag %d = %d", i, consumerFlag[i]); 
pthread_mutex_unlock(&mutex);         
}          
}
}
int main()
{
int i=0;
pthread_mutex_init(&mutex,0);
pthread_cond_init(&cond,0);   
pthread_t pThread, cThread;
pthread_create(&pThread, 0, producer, 0);
pthread_create(&cThread, 0, consumer,0);   
pthread_join(pThread,NULL);
pthread_join(cThread, NULL);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
return 0;
}

首先,我希望用户输入数组,然后 consumer 函数打印输入的数组,然后再次要求用户输入数组。

代码中几乎没有主要问题。

  1. 仅当线程之前已锁定互斥锁时,该线程才能解锁互斥锁。在您的代码中,互斥锁在循环函数外部锁定,并在循环内解锁。它将给出未定义的行为。
  2. 消费者函数在进入循环之前正在执行 signal_wait()。我想你已经假设生产者和消费者线程几乎同时启动,生产者在消费者锁定互斥锁之前不会发出信号。这是错误的。您应该假设线程以随机顺序调度并处理所有可能的情况。
  3. 当使用者完全使用数据时,您不会通知生产者。从消费者到生产者没有信号机制。
  4. 当生产者完全生成数据时,您正在通知消费者。但消费者并没有在循环时在外面等待。这意味着,只有一次它可能会收到通知。
  5. 在生产者中,condition_signal是在解锁互斥锁之后,这是错误的。应在互斥锁锁定的情况下呼叫信号。

因此,在生产者中,您需要生成数据,向消费者发送信号,并等待消费者确认数据被消费。您需要另外设置一个标志,以考虑生产者线程在使用者线程之前获取锁定的情况。在这种情况下,当生产者发送信号时,消费者不会进入 while 循环。所以消费者无法捕捉到信号。

void *producer(void *arg) 
{     
pthread_mutex_lock(&mutex);        
while(1)
{
printf("n Enter no of terms");
scanf("%d",&n);
int i; 
printf("n Enter consumer flag array");
for (i = 0; i < n; i++) 
{
scanf(" %d",&consumerFlag[i]);
//pthread_mutex_unlock(&mutex);  //Should not be unlocked in loop         
}
data_produced_flag = 1; //A flag to indicate data is ready. Should be initialized to 0 before thread creation. It is required if producer produces before consumer thread goes to pthread_cond_wait()
pthread_cond_signal(&cond_producer); //Should send signal with mutex locked
//usleep(1000); //Not required as it is going to wait for signal from consumer
pthread_cond_wait(&cond_consumer, &mutex); //Wait for confirmation that data is consumed
}
pthread_mutex_unlock(&mutex); 
}

在消费者函数中,您应该检查数据是否已经生成。如果未生成,请等待生产者的信号。当数据可用时,使用并发出信号生产者以获取最新数据。

void *consumer(void *arg) 
{
int i;
pthread_mutex_lock(&mutex);
//pthread_cond_wait(&cond, &mutex);  //Wait inside loop
printf("nConsumer Function"); 
while(1)
{
if(0 == data_produced_flag) 
{
printf("nConsumer thread waiting"); 
pthread_cond_wait(&cond_producer, &mutex); //Wait for signal from producer
}
//else
//{
//Data is already produced. No need to wait.
//}
//Data is available for consumption
for (i = 0; i < n; i++) 
{    
printf("nConsumerFlag %d = %d", i, consumerFlag[i]); 
//pthread_mutex_unlock(&mutex);    //We are in the process of consumption. Don't unlock mutex.
}
data_produced_flag = 0; //Reset the flag. Ready for new data.
pthread_cond_signal(&cond_consumer); //Indicate that data is consumed
}
pthread_mutex_unlock(&mutex); 
}

最新更新