生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例。
先说说同步和互斥的概念
同步是一种时序关系,即A处理完事情1后,B才能处理事情2,经典的同步问题是生产者和消费者间的同步。
互斥描述的是一种独占关系。如任一时刻,A和B中只能有一个写文件file。
生产者和消费者问题从易到难有三种。
先定义两个信号量。
sem_t empty_sem; // 同步信号量,初值为M,生产者用它来判断缓冲区是否可写,当满了时阻止生产者放产品。
sem_t full_sem; // 同步信号量,初值为0,消费者用它来判断缓冲区是否可读,当没产品时阻止消费者消费。
1. 一个生产者和一个消费者,公用一个缓冲区
producer(生产者)的伪码(M为1):
while(1) { sem_wait(&empty_sem); 写缓冲区; sem_post(&full_sem); }
consumer(消费者)的伪码:
while(1) { sem_wait(&full_sem); 写缓冲区; sem_post(&empty_sem); }
producer(生产者)的伪码(M>1):
while(1) { sem_wait(&empty_sem); 写第in个缓冲区; /* in用来指示当前的第一个可写的缓冲区的下标,初值设为0。 */ in = (in+1)%m; sem_post(&full_sem); }
while(1) { sem_wait(&full_sem); 读第out个缓冲区; /* out用来指示当前的第一个可读的缓冲区的下标,初值设为0。 */ out = (out+1)%m; sem_post(&empty_sem); }
相比第2种情况,我们所要做的是用两个互斥变量mutex_producer和mutex_consumer,来实现各生产者间、各消费者间互斥地访问某个缓冲区。
producer(生产者)的伪码(M>1):
while(1) { sem_wait(&empty_sem); pthread_mutex_lock(mutex_producer); 写第in个缓冲区; /* in用来指示当前的第一个可写的缓冲区的下标,初值设为0。 */ in = (in+1)%m; pthread_mutex_unlock(mutex_producer); sem_post(&full_sem); }
while(1) { sem_wait(&full_sem); pthread_mutex_lock(mutex_consumer); 读第out个缓冲区; /* out用来指示当前的第一个可读的缓冲区的下标,初值设为0。 */ out = (out+1)%m; pthread_mutex_unlock(mutex_consumer); sem_post(&empty_sem); }