生产者-消费者问题:
生产者-消费者问题是经典的同步问题,它描述一组生产者进程(线程)向一组消费者进程(线程)提供消息。它们共享一个有界的缓冲池,生产者向其中投放消息,消费者从中取得消息。生产者-消费者问题是许多具体问题中进程(线程)合作的一个很好的抽象。假定缓冲区中有N个位置,每个位置存放一个消息。当缓冲区未满时,生产者可以投入一个消息,否则该进程(线程)阻塞,直到缓冲区内有空位可放;当缓冲区非空时,消费者可以从中取得一个消息,否则该进程(线程)阻塞,直到缓冲区内有消息可取。
为了模拟这一过程,首先需要设置一个大小为N的缓冲区。修改缓冲区时,需要同步各个进程(线程)以免发生错误(向满的缓冲区投放消息或者从空缓冲区内取出消息)。为此,需要设置两个信号量empty和full用以标识缓冲区中空位数和消息数。另外还需要一个互斥锁mutex以互斥地修改缓冲区。为了便于测试,这里缓冲区的大小设置为5,实际情况下,应该尽量大些,以免生产者和消费者相互等待。
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | #include <iostream> #include <pthread.h> #include <semaphore.h> using namespace std; const int N = 5; sem_t empty; //~ 剩余空位数 sem_t full; //~ item数 pthread_mutex_t lock; //~ 互斥锁 typedef int item; //~ 产品类型 item buffer[N]; //~ 产品缓冲区 item new_item(); //~ 制造产品 void use_item(item&); //~ 使用产品 void * producer(void*); //~ 生产者进程 void *consumer(void*); //~ 消费者进程 int main() { //~ 初始化各信号量、互斥锁 sem_init(&empty, 0, N); sem_init(&full, 0, 0); pthread_mutex_init(&lock, NULL); //~ 消费者、生产者进程id pthread_t consumer_id; pthread_t producer_id; //~ 创建消费者、生产者进程 pthread_create(&consumer_id, NULL, consumer, NULL); pthread_create(&producer_id, NULL, producer, NULL); //~ join pthread_join(consumer_id, NULL); pthread_join(producer_id, NULL); //~ 销毁各信号量、互斥锁 sem_destroy(&empty); sem_destroy(&full); pthread_mutex_destroy(&lock); return 0; } item new_item() { return item(); } void use_item(item&) { } void * producer(void*) { while(true) { usleep(500000); //~ 延时0.5s item tmp = new_item(); int pos; sem_wait(&empty); //~ 等待空位 pthread_mutex_lock(&lock); //~ 获得互斥锁 sem_getvalue(&full, &pos); //~ 输出当前产品数 cout<<"item produced..."<<pos+1<<" in buffer..."<<endl; buffer[pos] = tmp; pthread_mutex_unlock(&lock); //~ 释放互斥锁 sem_post(&full); //~ 增加full } return NULL; } void *consumer(void*) { while(true) { sleep(1); //~ 延时1s item tmp; int pos; sem_wait(&full); //~ 没有产品则等待 pthread_mutex_lock(&lock); //~ 获得互斥锁 sem_getvalue(&full, &pos); cout<<"item consumed..."<<pos<<" in buffer..."<<endl; tmp = buffer[pos-1]; pthread_mutex_unlock(&lock); //~ 释放互斥锁 sem_post(&empty); //~ 增加空位数 use_item(tmp); } return NULL; } |
输出:
item produced...1 in buffer... item consumed...0 in buffer... item produced...1 in buffer... item produced...2 in buffer... item consumed...1 in buffer... item produced...2 in buffer... item produced...3 in buffer... item consumed...2 in buffer... item produced...3 in buffer... item produced...4 in buffer... item consumed...3 in buffer... item produced...4 in buffer... item produced...5 in buffer... item consumed...4 in buffer... item produced...5 in buffer... item consumed...4 in buffer... item produced...5 in buffer... item consumed...4 in buffer... item produced...5 in buffer...
由于生产者投放消息的速度要比消费者取用消息的速度快,缓冲区内的消息数逐渐增多,直至缓冲区满,需要消费者从中取出一个消息后生产者才能继续向其中投放消息。
你好!除了代码,此处没有多少原创之物,皆为本人搜集、整理、总结之记录与心得,欢迎转载分享!转载时请尽量注明出处,将不胜感激。祝你健康、快乐!
Be the first to comment on this entry.