实验五 进程同步问题实现

一、实验目的

利用实验四提供的方法和例子,解决进程同步相关问题,例如:生产者消费者问题,哲学家进餐等问题。

二、实验环境

硬件环境:计算机一台,局域网环境;

软件环境:Linux Ubuntu操作系统,gcc编译器

三、实验内容

运用实验四中提供的进程同步方法实现如下问题:

  1. 生产者消费者问题
  • 问题描述:一组生产者进程向一组消费者进程提供产品,两类进程共享一个由n个缓冲区组成的有界缓冲池,生产者进程向空缓冲池中投放产品,消费者进程从放有数据的缓冲池中取得产品并消费掉。

  • 只要缓冲池未满,生产者进程就可以把产品送入缓冲池;只要缓冲池未空,消费者进程便可以从缓冲池中取走产品。

  • 但禁止生产者进程向满的缓冲池再输送产品,也禁止消费者进程从空的缓冲池中提取产品。

  • 为了防止对缓冲池重复操作,故规定在任何时候,只有一个主体可以访问缓冲池。

    /** @Description: 多个生产者消费者问题* @version: * @Author: * @Date: 2021-04-30 13:53:49* @LastEditors: Please set LastEditors* @LastEditTime: 2021-04-30 15:59:14*/// NOTE:
    // *sem_init()初始化无名信号量,sem_open()是初始化有名信号量
    // *第一个参数是指向信号量的指针
    // *第二个参数为0,表示信号量只在这一进程的所有线程之间共享,否则,是进程间共享
    // *第三个参数是初始值// *线程互斥锁的创建,上锁与解锁
    // * int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t * attr)
    // * 第二个参数是锁的属性
    // *int pthread_mutex_lock(pthread_mutex_t *mutex)
    // *int pthread_mutex_unlock(pthread_mutex_t *mutex)// *int pthread_create((pthread_t *thread,  pthread_attr_t *attr,  void *(*start_routine)(void  *), void *arg)
    // * 线程标识符
    // * 线程属性
    // * 线程函数地址
    // * 传给函数的参数// ? 代码中如果没有pthread_join主线程会很快结束从而使整个进程结束,从而使创建的线程没有机会开始执行就结束了。加入pthread_join后,主线程会一直等待直到等待的线程结束自己才结束,使创建的线程有机会执行。
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <pthread.h>
    #include <semaphore.h>#define PRODUCER_NUM 5 //生产者数目
    #define CONSUMER_NUM 5 //消费者数目
    #define POOL_SIZE 11   //缓冲池大小int pool[POOL_SIZE];   //缓冲区
    int head = 0;          //缓冲池读取指针
    int rear = 0;          //缓冲池写入指针
    sem_t empty_sem;       //同步信号信号量,表示缓冲区有可用空间
    sem_t full_sem;        //同步信号量,表示缓冲区有可用产品
    pthread_mutex_t mutex; // 缓冲区互斥访问,线程互斥锁
    // 生产者
    void *producer_fun(void *arg)
    {while (1){sleep(1);/* 空间-- */sem_wait(&empty_sem);// 关闭互斥信号量pthread_mutex_lock(&mutex);//生产者往缓冲池中写入数据pool[rear] = 1;rear = (rear + 1) % POOL_SIZE;printf("producer %d write to pool\n", (int)arg);printf("pool size is %d\n", (rear - head + POOL_SIZE) % POOL_SIZE);// 打开互斥信号量pthread_mutex_unlock(&mutex);// 产品++sem_post(&full_sem);}
    }
    // 消费者
    void *consumer_fun(void *arg)
    {while (1){int data;sleep(10);// 检查是否是产品sem_wait(&full_sem);// 关闭互斥信号量pthread_mutex_lock(&mutex);//消费者从缓冲池读取数据data = pool[head];head = (head + 1) % POOL_SIZE;printf("consumer %d read from pool\n", (int)arg);printf("pool size is %d\n", (rear - head + POOL_SIZE) % POOL_SIZE);// 打开互斥信号量pthread_mutex_unlock(&mutex);// 空闲位置++sem_post(&empty_sem);}
    }int main()
    {int i;pthread_t producer_id[PRODUCER_NUM];    // 生产者线程数组pthread_t consumer_id[CONSUMER_NUM];    // 消费者线程数组pthread_mutex_init(&mutex, NULL);       //初始化互斥量sem_init(&empty_sem, 0, POOL_SIZE - 1); //初始化信号量empty_sem为缓冲池大小sem_init(&full_sem, 0, 0);              //初始化信号量full_sem为0,开始时缓冲池中没有数据for (i = 0; i < PRODUCER_NUM; i++){//创建生产者线程pthread_create(&producer_id[i], NULL, producer_fun, (void *)i);//创建消费者线程pthread_create(&consumer_id[i], NULL, consumer_fun, (void *)i);}for (i = 0; i < PRODUCER_NUM; i++){pthread_join(producer_id[i], NULL);pthread_join(consumer_id[i], NULL);}exit(0);
    }
    

  1. 哲学家进餐问题
  • 有5位哲学家倾注毕生精力用于思考和吃饭,他们围坐在一张圆桌旁,在圆桌上有5个碗和5支筷子。每位哲学家的行为通常是思考,当其感到饥饿时,便试图取其左右最靠近他的筷子进餐。只有他拿到两支筷子后才能进餐,进餐完毕后,释放两支筷子并继续思考。

  • 要求:采取合适的方法,防止出现死锁的问题

    /** @Description: 哲学家进餐问题* @version: * @Author: * @Date: 2021-04-30 14:51:12* @LastEditors: Please set LastEditors* @LastEditTime: 2021-05-14 14:13:54*/
    #include <stdio.h>
    #include <stdlib.h>
    #include <pthread.h>
    #include <semaphore.h>
    #include <unistd.h>
    // 至多只允许4位哲学家竞争筷子,这样就一定有一个哲学家可以拿到两支筷子
    #define N 5                               // 五个哲学家
    #define TIME_EAT 5                        // 吃饭的时间
    #define TIME_THINK 5                      // 思考的时间
    #define LIMIT 4                           // 同一时间只允许4人用餐
    #define left(phi_id) (phi_id + N - 1) % N // 宏函数,计算哲学家左手边的筷子,注意id可能为0,所以要+N
    #define right(phi_id) (phi_id + 1) % N    // 宏函数,计算哲学家右手边的筷子
    sem_t chopstick[N]; // 筷子互斥信号量数组
    sem_t limit;        // 竞争人数void thinking(int id)
    {sleep(TIME_THINK);printf("philosopher[%d] is thinking...\n", id);
    }void eating(int id)
    {sleep(TIME_EAT);printf("philosopher[%d] is eating...\n", id);
    }void take_forks(int id)
    {//获取左右两边的筷子sem_wait(&chopstick[left(id)]);sem_wait(&chopstick[right(id)]);printf("philosopher[%d]  take_forks...\n", id);
    }void put_down_forks(int id)
    {printf("philosopher[%d] is put_down_forks...\n", id);sem_post(&chopstick[left(id)]);sem_post(&chopstick[right(id)]);
    }void *philosopher_work(void *arg)
    {int id = *(int *)arg;printf("philosopher init [%d] \n", id);while (1){thinking(id);// 检查同时竞争的哲学家是否达到限制,是则阻塞等待,否则进入竞争sem_wait(&limit);take_forks(id);// 已经拿到了筷子,退出竞争sem_post(&limit);eating(id);// 进食完毕,释放筷子put_down_forks(id);}
    }int main()
    {// 线程数组,相当于N个哲学家pthread_t phiTid[N];int i;int *id = (int *)malloc(sizeof(int) * N);// 初始化筷子信号量,初始情况是,所有筷子都空闲for (i = 0; i < N; i++)sem_init(&chopstick[i], NULL, 1);// 初始化信号量,初始值是LIMIT,无人参与竞争sem_init(&limit, NULL, LIMIT);for (i = 0; i < N; ++i){id[i] = i;// 生成的thread id是0,1,2,3,4,(iny*)->(void*)pthread_create(&phiTid[i], NULL, philosopher_work, (void *)(&id[i]));}while (1);exit(0);
    }
    

  1. 和尚打水问题
  • 某寺庙,有小和尚,老和尚若干。有一水缸,由小和尚提水入缸供老和尚饮用。水缸可容10桶水,水取自同一井中。水井径窄,每次中能容下一个桶取水。水桶总数为3个。每人一次取缸水仅为1桶,且不可同时进行。

    /** @Description: 和尚打水问题* @version: * @Author: * @Date: 2021-04-30 15:27:58* @LastEditors: Please set LastEditors* @LastEditTime: 2021-04-30 16:46:49*/
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <pthread.h>
    #include <semaphore.h>
    #include <stdbool.h>
    // mutex1是井的互斥信号量
    // mutex2是缸的互斥信号量
    // amount是桶的互斥信号量
    // empty和full是缸的同步信号量
    sem_t mutex1, mutex2, amount, empty, full;
    int fullcount = 0;
    void *LittleMonk(void *p)
    {while (true){// 检查是否空,若空则打水,否则阻塞等待sem_wait(&empty);// 检查是否有桶可用,有则去访问井,否则阻塞等待sem_wait(&amount);// 检查有没有其他小和尚正在访问井sem_wait(&mutex1);// 井边提水printf("第%d个小和尚在水井提水\n", *(int *)p);// 打完水后释放井的信号量,离开井sem_post(&mutex1);// 检查是否有其他和尚正在访问缸,若没有则倒水,否则阻塞等待sem_wait(&mutex2);// 小和尚在水缸旁倒水printf("水缸已有%d桶水,第%i个小和尚在水缸旁倒水\n", fullcount, *(int *)p);// 缸内水的数量++fullcount++;// 倒水的小和尚离开缸,释放资源sem_post(&mutex2);// 放下水桶,释放桶资源sem_post(&amount);// 水缸里水的桶数加1sem_post(&full);}
    }
    void *BigMonk(void *p)
    {while (true){// 检查缸内是否有水,有则打水,否则阻塞等待sem_wait(&full);// 老和尚检查是否有水桶可用,没有水桶则等待sem_wait(&amount);// 水缸旁有人则等待,没有则开始打水sem_wait(&mutex2);printf("\t水缸已有%d桶水,第%d个大和尚在水缸旁提水\n", fullcount, *(int *)p);// 打完水,缸内水的数量--fullcount--;// 老和尚离开缸,释放缸互斥信号量sem_post(&mutex2);// 老和尚放下水桶,是否同互斥信号量sem_post(&amount);// 空闲位置++sem_post(&empty);}
    }int main()
    {int i, j;// 保存进程的IDpthread_t little[20], big[20];//初始化信号量// 井互斥锁默认为1sem_init(&mutex1, 0, 1);// 缸互斥锁默认为1sem_init(&mutex2, 0, 1);// 开始时有3个水桶供使用sem_init(&amount, 0, 3);// 开始时水缸里没有水,设置为0sem_init(&full, 0, 0);// 开始时水缸里最多能装10桶水,设置为10sem_init(&empty, 0, 10);//创建多个老和尚进程for (i = 1; i <= 4; ++i){int *id = &i;pthread_create(&big[i], NULL, BigMonk, (void *)id);}//创建多个小和尚进程for (j = 1; j <= 10; ++j){int *id = &j;pthread_create(&little[j], NULL, LittleMonk, (void *)id);}while (true);exit(0);
    }
    

四、实验总结

结合实验,谈谈你对进程同步的理解和体会。

  • 进程同步是指并发执行的进程因直接制约关系而需相互等待,相互合作,以实现各进程按相互协调的速度向前推进的过程。同步过程中进程与进程之间有序合作,相互清楚对方的存在及其作用,进程之间直接合作完成任务。

操作系统 实验五 进程同步问题实现相关推荐

  1. 操作系统实验五:用户进程管理(详细分析)

    操作系统实验五:用户进程管理 一. 实验目的 二. 实验任务 三. 实验准备 1.alloc_proc() 函数 2.do_fork() 函数 3.idt_init() 函数 4.trap_dispa ...

  2. 操作系统实验五--存储管理

    文章目录 操作系统实验五--存储管理 一.实验目的 二.实验内容 三.设计原理及相关算法 四.结果分析 五.源代码 操作系统实验五–存储管理 一.实验目的 1.了解虚拟存储技术的特点,掌握请求页式存储 ...

  3. 操作系统实验五 存储管理

    ★观前提示:本篇内容为操作系统实验内容,代码等内容经测试没有问题,但是可能会不符合每个人实验的要求,因此以下内容建议仅做思路参考. 目录 一.实验目的 二.实验内容 三.具体实现 四.实验总结 一.实 ...

  4. 操作系统实验五:文件管理

    实验五 文件管理 一.实验要求 (1)了解文件权限及作用: (2)掌握文件权限的设置: (3)掌握文件权限的管理与应用: (4)掌握文件基本操作: (5)理解文件系统管理文件的实现机制. 二.实验内容 ...

  5. 操作系统实验五 基于内核栈切换的进程切换(哈工大李治军)

    实验5 基于内核栈切换的进程切换 实验目的 深入理解进程和进程切换的概念: 综合应用进程.CPU 管理.PCB.LDT.内核栈.内核态等知识解决实际问题: 开始建立系统认识. 实验内容 现在的 Lin ...

  6. 南京邮电大学操作系统实验五:Windows平台多进程共享内存通信

    实验内容 1.理解Windows同步互斥机制中的等待函数.事件内核对象.信标内核对象.互斥对象内核对象.动态链接库.DLL整体运行情况.创建DLL模块和相关函数部分. DLL程序入口点函数为DllMa ...

  7. 操作系统实验四 进程同步与互斥

    一.实验目的: 掌握基本的同步与互斥算法,理解P,V操作. 理解生产者消费者模型,了解其它典型的同步互斥模型,如哲学家就餐.读者-写者模型等. 了解LINUX中进程同步互斥的实现方法,掌握相关函数的使 ...

  8. 操作系统实验五·xv6系统内存布局修改·栈空间位置变更与栈不足时扩充

    xv6系统内存布局修改·栈空间位置变更与栈不足时扩充 1.实验目的 2.实验内容 3. 实验手册 4. 实验环境 5. 程序设计和实现 5.1系统函数修改 5.2 编译运行 6. 实验结果和分析 1. ...

  9. 操作系统实验五、进程互斥实验——理发店问题

    问题描述 理发店问题:假设理发店的理发室中有 3 个理发椅子和 3 个理发师,有一个可容纳4个顾客坐等理发的沙发.此外还有一间等候室,可容纳13位顾客等候进入理发室.顾客如果发现理发店中顾客已满(超过 ...

最新文章

  1. 【数据平台】dataframe一列成多列
  2. excel打开空白_PDF转成Excel后,打开表格却是空白的?
  3. mybatis的SelectKey属性的作用
  4. 从bsp redirect到ui5_ui5
  5. js call(),apply(),对象冒充,改变变量作用域
  6. java.lang.IllegalArgumentException: Does not contain a valid host:port authority: ignorethis
  7. mysql 回滚失败_Mysql非事务表回滚失败的现象
  8. hibernate简单入门教程(四)---------关联映射
  9. CentOS下安装JDK完整步骤
  10. 黑苹果使用Hackintool注入声卡驱动
  11. 软考软件测评师学习笔记(一)
  12. 获取深户股市列表api_获取股票api
  13. 关于#pragma comment(lib,ws2_32.lib)
  14. 小米手环6NFc支持Android,小米手环6支持nfc吗 小米手环6有没有nfc功能
  15. tips:如何在chrome浏览器的网页中截长图
  16. 一文详解!你真的了解商业智能BI吗?
  17. 视频教程:Java常见面试题目深度解析!
  18. RK3288 android添加HAL 层导致无法进入主界面原因分析,重复打印 camsys_marvin(deaa1510) is closed
  19. image图片大小调整和方向调整(UIImageOrientation)
  20. 同样是技术出身,深夜看完王兴饭否的190条思考,越想越后怕!

热门文章

  1. 李国杰:云计算不可忽视计算机系统研究
  2. 会声会影X9无法正常启动0xc000007b
  3. Proteus 实现一百分钟倒计时计数器
  4. 在平台上便捷使用LS-DYNA的方式
  5. Differential privacy——差分隐私
  6. 32个Python爬虫实战项目,满足你的项目慌(带源码)
  7. 【android入门基础】黑马训练营的android培训——08
  8. 给你的导航页加把锁—php简单登录后进入导航
  9. media social 指什么_什么是social media?
  10. php购买鲜花流程,鲜花同城配送怎么操作?操作流程和注意事项详解