对于生产者-消费者问题,有时候也称为有界缓冲区(bounded-buffer)问题。两个进程共享一个公共的固定大小的缓冲区。其中一个是生产者,将消息放入缓冲区;另一个是消费者,从缓冲区取出消息。(也可以把这个问题一般化为m个生产者和n个消费者的问题,但是我们只讨论一个生产者和一个消费者的问题,这样可以简化解决方案)。
对于这个问题解决的逻辑是这样的:这个问题在于当缓冲区已满,而此时生成者还想向其中放入一个新的数据项的情况。其解决的办法。是让生产者睡眠,待消费者从缓冲区取出一个或者多个数据项时再唤醒它。同样地,当消费者试图从缓冲区取数据而发现缓冲区为空,消费者就睡眠,直到生产者向其中放入一些数据时再将其唤醒。
生产者-消费者,c语言解决办法:
#define N 100
int count = 0;
void producer(void)
{
int item;
while(TRUE){
item = produce_item();
if(count == N) sleep();
insert_item(item);
count = count + 1;
if(count == 1) wakeup(consumer);
}
}
void consumer(void)
{
int item;
while(TRUE){
if(count==0)sleep();
item = remove_item();
count = count -1;
if(count = N-1) wakeup(producer);
consume_item(item);
}
}
使用信号量解决的生产者-消费者问题:
#define N 100
typedef int semaphore;
semaphore mutex = 1;
semaphore empty =1;
semaphore full = 0;
void producer(void)
{
int item;
while(TRUE){
item = produce_item();
down(&empty);
down(&mutex);
insert_item(item);
up(&mutex);
up(&full);
}
}
void consumer(void)
{
int item;
while(TRUE){
down(&full);
down(&mutex);
item = remove_item();
up(&mutex);
up(&empty);
consume_item(item);
}
}
利用线程解决生产者消费者问题(要研究线程、互测量、条件变量),下面这是在只有一个缓冲区的生产者-消费者问题:
#include <stdio.h>
#include <pthread.h>
#define MAX 1000000000
pthread_mutex_t the_mutex;
pthread_cond_t condc,condp;
int buffer = 0;
void *producer(void *ptr)
{
int i;
for(int i=1;i<= MAX ;i++){
pthread_mutex_lock(&the_mutex);
while(buffer != 0)pthread_cond_wait(&condp,&the_mutex);
buffer = i;
pthread_cond_signal(&condc);
pthread_mutex_unlock(&the_mutex);
}
pthread_exit(0);
}
void *consumer(void *ptr)
{
int i;
for(i = 1;i <= MAX,i++){
pthread_mutex_lock(&the_mutex);
while(buffer ==0) pthread_cond_wait(&condc,&the_mutex);
buffer = 0;
pthread_cond_signal(&condp);
pthread_mutex_unlock(&the_mutex);
}
pthread_exit(0);
}
int main(int argc,char **argv)
{
pthread_t pro,con;
pthread_mutex_init(&the_mutex,0);
pthread_cond_init(&condc,0);
pthread_cond_init(&condp,0);
pthread_create(&con,0,consumer,0);
pthread_create(&pro,0,producer,0);
pthread_join(pro,0);
pthread_join(con,0);
pthread_cond_destory(&condc);
pthread_cond_destory(&condp);
pthread_mutex_destory(&the_mutex);
}
对于,java语言由于其支持管程(管程是编程语言的概念,c/c++/pascal语言均不支持),所以处理上面来说比较方便;
下面是使用java语言实现的生产者-消费者问题的解法:
public class ProducerConsumer{
static final int N = 100;
static producer p = new producer();
static consumer c = new consumer();
static our_monitor mon = new our_monitor();
public static void main(String args[]){
p.start();
p.start();
}
static class producer extends Thread{
public void run(){
int item;
while(true){
item = produce_item();
mon.insert(item);
}
}
private int produce_item(){.....}//实际生产
}
static class consumer extends Thread{
public void run(){
int item;
while(true){
item = mon.remove();
consume_item(item);
}
}
private void consume_item(int item){...}//实际消费
}
static class our_monitor{
private int buffer[] = new int[N];
private int count = 0,lo = 0,hi = 0;
public synchronized void insert(int val){
if(count == N) go_to_sleep();
buffer[hi] = val;
hi = (hi +1) % N;
count = count +1;
if(count ==1)notify();
}
public synchronized int remove(){
int val;
if(count == 0)go_to_sleep();
val = buffer[lo];
lo = (lo +1)%N;
count = count -1;
if(count == N-1) notify();
return val;
}
private void go_to_sleep(){try{wait();}catch(){InterruptedException exc};}
}
}
用N条消息实现的生产者-消费者问题
#define N 100
void producer(void)
{
int item;
message m;,
while(TRUE){
item = produce_item();
receive(consumer,&m);
build_message(&m,item);
send(consumer,&m);
}
}
void consumer(void)
{
int item,i;
message m;
for(i = 0;i<N; i++)send(producer,&m);
while(TRUE){
receive(producer,&m);
item = extract_item(&m);
send(producer,&m);
consume_item(item);
}
}