操作系统第6次实验报告:使用信号量解决进程互斥访问
- 姓名:祁翌炀
- 学号:201821121019
- 班级:计算1811
1. 选择哪一个问题
选题哪个问题?
- 生产者-消费者问题
2. 给出伪代码
在相同的地址空间执行两个线程,生产者线程生产产品,消费者获得产品进行消费。
生产产品将物品放在缓存区等消费者消费。消费者从那边获取产品然后释放缓存区。
生产者如果生产产品的时候没有缓冲区可用,那么就必须等待消费者释放一个空缓存区后才能继续执行,
消费者如果没有已经满的缓存区,那消费者就要等待新的产品生产出来。
int main()//此处为主函数,也为算法函数。在之前有生产者和消费者的操作函数。 { pthread_t threadPool[producerNum+consumerNum]; int i; for(i = 0; i < producerNum; i++){ //这边即为生产定义的10个产品, pthread_t temp; if(pthread_create(&temp, NULL, producer, NULL) == -1){//如果全部都是满的话,就退出让消费者进行消费。 printf("ERROR, fail to create producer%d\n", i); exit(1); } threadPool[i] = temp; }//创建生产者进程放入线程池 for(i = 0; i < consumerNum; i++){//同理 pthread_t temp; if(pthread_create(&temp, NULL, consumer, NULL) == -1){//如果都是空的话,就让生产者进行生产。 printf("ERROR, fail to create consumer%d\n", i); exit(1); } threadPool[i+producerNum] = temp; }//创建消费者进程放入线程池 void * result; for(i = 0; i < producerNum+consumerNum; i++){//这边为运行线程池,也为打印。 if(pthread_join(threadPool[i], &result) == -1){ printf("fail to recollect\n"); exit(1); } }//运行线程池 return 0; }
3. 给出完整代码
#include <stdio.h> #include <pthread.h> #include <windows.h> #define N 100 #define true 1 #define producerNum 10 #define consumerNum 5 #define sleepTime 1000 typedef int semaphore; typedef int item; item buffer[N] = {0}; int in = 0; int out = 0; int proCount = 0; semaphore mutex = 1, empty = N, full = 0, proCmutex = 1; void * producer(void * a){ while(true){ while(proCmutex <= 0); proCmutex--; proCount++; printf("生产产品ID=%d, 缓冲区位置=%d\n",proCount,in); proCmutex++; while(empty <= 0){ printf("缓冲区无位置分配\n"); } empty--; while(mutex <= 0); mutex--; buffer[in] = proCount; in = (in + 1) % N; mutex++; full++; Sleep(sleepTime); } } void * consumer(void *b){ while(true){ while(full <= 0){ printf("消费完了,缓冲区为空\n"); } full--; while(mutex <= 0); mutex--; int nextc = buffer[out]; buffer[out] = 0;//消费完将缓冲区设置为0 out = (out + 1) % N; mutex++; empty++; printf("\n"); printf("消费产品ID=%d,缓冲区位置=%d\n", nextc,out); sleep(sleepTime); } } int main() { pthread_t threadPool[producerNum+consumerNum]; int i; for(i = 0; i < producerNum; i++){ pthread_t temp; if(pthread_create(&temp, NULL, producer, NULL) == -1){ printf("ERROR, fail to create producer%d\n", i); exit(1); } threadPool[i] = temp; }//创建生产者进程放入线程池 for(i = 0; i < consumerNum; i++){ pthread_t temp; if(pthread_create(&temp, NULL, consumer, NULL) == -1){ printf("ERROR, fail to create consumer%d\n", i); exit(1); } threadPool[i+producerNum] = temp; }//创建消费者进程放入线程池 void * result; for(i = 0; i < producerNum+consumerNum; i++){ if(pthread_join(threadPool[i], &result) == -1){ printf("fail to recollect\n"); exit(1); } }//运行线程池 return 0; }
4. 运行结果并解释
此处为正常的生产和消费,并且不会造成互斥,因为此时既有富足的空地址也有有内容的产品地址。
此处为生产区已经生产太多了,造成消费不及时已经满的情况,这个时候停止生产等待消费。
所以我又启动了第二个程序,这样就让他们迅速消费,消费完了的时候也能发现,他生产和消费的id数一样,因为变成了生产
多少个,再消费多少个的,后面就有间隔了,因为生产的速度比消费的快,
所以会先把缓存区都存满,也就是上一个的截图结果。
当先启动的时候没有生产就直接消费,就会提示缓存区为空,需要生产新的产品