操作系统第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数一样,因为变成了生产

多少个,再消费多少个的,后面就有间隔了,因为生产的速度比消费的快,

所以会先把缓存区都存满,也就是上一个的截图结果。

当先启动的时候没有生产就直接消费,就会提示缓存区为空,需要生产新的产品

 

posted @ 2020-05-31 11:39  QBB  阅读(196)  评论(0编辑  收藏  举报