中北大学软件学院操作系统实验报告之实验一进程同步

实验时间

2024年 4 月13日14时至16时

学时数

2

1.实验名称

实验一进程同步

2.实验目的

(1)加强对进程概念的理解,尤其是对进程的同步与互斥机制的理解。

(2)分析进程竞争资源的现象,学习解决进程互斥与同步的方法。

  1. 实验内容

(1)编程实现生产者-消费者问题的模拟(建议用C语言编写源代码)。

基本要求:

(1)生产者消费者对缓冲区进行互斥操作。

(2)缓冲区大小为10,缓冲区满则不允许生产者生产数据,缓冲区空则不允许消费者消费数据。

(3)生产者消费者各循环操作10次。

4.实验原理或流程图

问题分析:这是一个同步与互斥共存的问题。

1.生产者—消费者问题是一个同步问题。即生产者和消费者之间满足如下条件:

2.由于有界缓冲区是临界资源,因此,各生产者进程和各消费者进程之间必须互斥执行。

故设置一个互斥信号量mutex,其初值为1。

注意:

1.进程应该先申请资源信号量,再申请互斥信号量,顺序不能颠倒。

2.对任何信号量的wait与signal操作必须配对。

3.对同一个信号量的wait与signal可以不在同一个进程中。

5.实验过程或源代码

#include <stdio.h>
#include <pthread.h>//pthread_create()函数的头文件
#include <windows.h>//sleep的头文件 
#define N 10
#define true 1
#define sleepTime 1000//1000就是1S
#define producerNum 10
#define consumerNum 10
typedef int semaphore;
typedef int item;


item buffer[N] = {0}; //缓冲池的情况
int in = 0; //生产者的指针
int out = 0; //消费者的指针
semaphore mutex = 1; //互斥性信号量
semaphore empty = N; //空着的缓冲区数
semaphore full = 0; //有东西的缓冲区数

void *producer(void *a) {
    while (true) {
        while (empty <= 0) {
            printf("缓冲区已满!\n");
        }
        empty--;//执行P操作

        while (mutex <= 0); //判断是否能进入缓冲区(mutex=1可入)
        mutex--;//进行P操作

        buffer[in] = 1; //生产完缓冲区设置为1
        in = (in + 1) % N; //是环形存储为了防止出现假溢出的现象

        mutex++;//执行V操作
        full++;//上下两步可调整先后
        Sleep(sleepTime);
        //当我们设置sleep时,等于告诉cpu,当前的线程不再运行,持有当前对象的锁。
        //那么这个时候cpu就会切换到另外的线程了。这种操作有些时候是非常好的。
    }
}

void *consumer(void *b) {
    while (true) {
        while (full <= 0) {
            printf("缓冲区为空!\n");
        }
        full--;//执行P操作

        while (mutex <= 0);
        mutex--;

        int nextc = buffer[out];
        buffer[out] = 0; //消费完将缓冲区设置为0
        out = (out + 1) % N;

        mutex++;
        empty++;

        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;
        //pthread_t是一个表示线程的数据类型
        //pthread_create是用来创建线程的
        if (pthread_create(&temp, NULL, producer, NULL) == -1) {
            //pthread_create的第一个参数是指向线程标识符的指针
            //第二个参数是用来设置线程的属性(一般不用设置所以一般为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;
}

  1. 实验结论及心得

代码运行部分截图

先学习了用记录型信号量,AND信号量解决问题,然后学习了管道机制,逐渐加深对操作系统的理解。

  • 25
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值