“完成一段代码,代码有三个线程。主线程有main进入,启动一个生产者和一个消费者线程。生产者线程随机产生整数,并且把这个整数放入一个List中,消费者从List中取出数据进行显示。”(摘自淘宝校招笔试题)
生产者-消费者问题是一个经典的线程同步问题。生产者将产品投入缓冲区,消费者从缓存区取出产品处理。很简单的一句话隐含着两个重要的内容:
- 若缓存为空,那么消费者程序必须等待;
- 若缓存已满,那么生产者程序必须等待。
相应的解决办法:
- 每个时间段只由一个线程可以使用缓存--互斥锁;
- 缓存已满生产者等待或者缓存已空消费者等待--条件变量。
下面是我写的一个程序以供参考:
#include<iostream> #include<stdlib.h> #include<unistd.h> #include<pthread.h> #include<vector> #include<time.h> using namespace std; #define MAX 10 //最大缓存 int num1=3; //生产者个数 int num2=5; //消费者个数 vector<int> buffer; //缓存 void *produce(void *); void *consume(void *); static pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t full=PTHREAD_COND_INITIALIZER; static pthread_cond_t empty=PTHREAD_COND_INITIALIZER; int main() { buffer.clear(); pthread_t tid1[num1],tid2[num2]; int ret=0,i; for(i=0;i<num1;i++) { if((ret=pthread_create(&tid1[i],NULL,produce,(void *)i))!=0) cout<<"create thread error! "<<endl; } for(i=0;i<num2;i++) { if((ret=pthread_create(&tid2[i],NULL,consume,(void *)i))!=0) cout<<"create thread error! "<<endl; } for(i=0;i<num1;i++) pthread_join(tid1[i],NULL); for(i=0;i<num2;i++) pthread_join(tid2[i],NULL); return 0; } void *produce(void *argc) { while(1) { pthread_mutex_lock(&mutex); while(buffer.size()>=MAX) { pthread_cond_wait(&full,&mutex); } int temp; srand((unsigned)time(NULL)); temp=rand()%100; cout<<"produce "<<pthread_self()<<": "<<temp; cout<<" buffer大小: "<<buffer.size()<<endl; buffer.push_back(temp); usleep(1000000); pthread_cond_broadcast(&empty); pthread_mutex_unlock(&mutex); usleep(1000000); } } void *consume(void *argc) { while(1) { pthread_mutex_lock(&mutex); while(buffer.size()<=0) { pthread_cond_wait(&empty,&mutex); } int temp; temp=buffer.back(); cout<<"consume "<<pthread_self()<<": "<<temp; cout<<" buffer大小: "<<buffer.size()<<endl; buffer.pop_back(); pthread_cond_broadcast(&full); usleep(1000000); pthread_mutex_unlock(&mutex); usleep(1000000); } }