使用POSIX标准中的Pthreads API来创建多个生产者、消费者线程
定义线程:pthread_t tid
创建线程:pthread_create(&tid,&attr,runner,argv[1]);
join线程:pthread_join(tid,NULL);
使用PthreadsAPI的信号量机制互斥与同步
定义信号量:sem_t sem
初始化信号量:sem_init(&sem, 0, n);
P操作:sem_wait(&sem);
V操作:sem_post(&sem);
#include <stdio.h> #include <pthread.h> #include <semaphore.h> #define BUFF_SIZE 5 // 定义缓冲区buffer大小为5 int buffer[BUFF_SIZE]; // 用循环队列模拟缓冲区 int in = 0; // 产品进缓冲区时的缓冲区下标 int out = 0; // 产品出缓冲区时的缓冲区下标 int productID = 0; // 产品号 int consumeID = 0; // 将被消耗的产品号 sem_t s; // 定义互斥信号量, 互斥锁s sem_t n; // 定义同步信号量n, buffer中已放入的产品个数 sem_t e; // 定义同步信号量e, buffer中空单元个数 // 生产一个产品, 输出新产品的ID号 void produce() { printf("成功生产了第:%d个产品\n",++productID); } // 把新生产的产品放入buffer void appen() { printf("将新生产的产品放入缓冲区\n"); buffer[in] = productID; in = (in+1)%BUFF_SIZE; int i; // 输出缓冲区当前的状态 for(i = 0; i<BUFF_SIZE; i++) { printf("i : %d",buffer[i]); if(i == in) printf("<-生产"); if(i == out) printf("<-消费"); printf("\n"); } printf("\n"); } // 生产者 void * Producer() { while(1) { sem_wait(&e); // 生产者首先试图拿一个buffer空单元, 获取一个空单元 sem_wait(&s); // 获取互斥锁s, 对临界区加锁, 互斥访问临界区buffer produce(); // 生产一个产品 appen(); // 把新生产的产品放入buffer Sleep(1000); // 模拟实际生产, 耗时1S sem_post(&s); // 临界区buffer访问完毕, 释放互斥锁s sem_post(&n); // 生产者任务完成, 释放一个产品 } } // 从buffer中取出一个产品 void take() { printf("从缓冲区中取出第:%d个产品\n",++consumeID); consumeID = buffer[out]; out = (out+1)%BUFF_SIZE; int i; // 输出缓冲区当前的状态 for(i = 0; i<BUFF_SIZE; i++) { printf("i : %d",buffer[i]); if(i == in) printf("<-生产"); if(i == out) printf("<-消费"); printf("\n"); } } // 消耗一个产品 void consume() { printf("消费了%d个产品\n\n",consumeID); } // 消费者 void * Consumer() { while(1) { sem_wait(&n); // 消费者首先试图拿一个buffer产品,获取一个产品 sem_wait(&s); // 获取互斥锁s,对临界区加锁,互斥访问临界区buffer take(); // 从buffer中取出一个产品 consume(); // 消耗一个产品 Sleep(1000); // 模拟实际消费,耗时1S sem_post(&s); // 临界区buffer访问完毕,释放互斥锁s sem_post(&e); // 生产者任务完成,释放一个buffer空单元 } } int main() { // 调整下面的数值,可以发现,当生产者个数多于消费者个数时, // 生产速度快,生产者经常等待消费者;反之,消费者经常等待 // 生产者的个数 int P_COUNT = 2; // 消费者的个数 int C_COUNT = 1; pthread_t p[P_COUNT],c[C_COUNT]; // 创建各个信号 sem_init(&s,0,1); // 初始化信号量s为互斥锁 sem_init(&n,0,0); // 初始化信号量n:buffer中已放入的产品数目(初始为0) sem_init(&e,0,BUFF_SIZE); // 初始化buffer中单元数目为BUFF_SIZE int i = 0; // 创建生产者线程 for(i = 0; i < P_COUNT; i++) { pthread_create(&p[i],NULL,Producer,NULL); pthread_create(&c[i],NULL,Consumer,NULL); } // 创建消费者线程 for(i = 0; i < C_COUNT; i++) { pthread_join(p[i],NULL); pthread_join(c[i],NULL); } }
Console输出:
成功生产了第:1个产品
将新生产的产品放入缓冲区
i : 1<-消费
i : 0<-生产
i : 0
i : 0
i : 0
成功生产了第:2个产品
将新生产的产品放入缓冲区
i : 1<-消费
i : 2
i : 0<-生产
i : 0
i : 0
成功生产了第:3个产品
将新生产的产品放入缓冲区
i : 1<-消费
i : 2
i : 3
i : 0<-生产
i : 0
从缓冲区中取出第:1个产品
i : 1
i : 2<-消费
i : 3
i : 0<-生产
i : 0
消费了1个产品
从缓冲区中取出第:2个产品
i : 1
i : 2
i : 3<-消费
i : 0<-生产
i : 0
消费了2个产品
成功生产了第:4个产品
将新生产的产品放入缓冲区
i : 1
i : 2
i : 3<-消费
i : 4
i : 0<-生产
成功生产了第:5个产品
将新生产的产品放入缓冲区
i : 1<-生产
i : 2
i : 3<-消费
i : 4
i : 5
...
...