进程互斥的软件实现方法-第二十六天

news2024/11/27 23:47:39

目录

前言

单标志法(谦让)

双标志先检查法(表达意愿)

双标志后检查法(表达意愿)

Peterson算法(集大成者)

本节思维导图


前言

        单标志法、双标志的先后检查法中,如果单个进程能一气呵成的执行完是没有问题的,但是如果出现进程切换的问题就会导致它们产生问题

单标志法(谦让)

谦让

基本思想:两个进程在访问完临界区后会把适用临界区的权限转交给另一个进程,即每个进程进入临界区的权限只能被另一个进程赋予

int turn = 0; //表示当前允许进入临界区的进程号

//P0进程
while (turn != 0)①   //进入区
critical section;②   //临界区
turn = 1;        ③   //退出区
remainer section;④   //剩余区


//P1进程
while(true != 1)  ⑤   //进入区
ctritical section;⑥   //临界区
true = 0;         ⑦   //退出区
remainder section;⑧   //剩余区

解释:trun初始值为0,即刚开始只允许P0进程进入临界区。若P0进程分配的时间片用完,P1进程要上处理机运行,则它会一直停留在⑤,直到分配给P1的时间片耗尽,然后又切换P0上处理机运行。只有在P0在退出区将true改为1后,P1才能进入临界区

结论:该算法可以实现“同一时刻最多只允许一个进程访问临界区”

缺点:违反“空闲让进”原则(只能按p0->p1->p0->p1->...这样轮流访问,这就会导致如果此时允许进入临界区的进程是p0,而p0一直不访问临界区,,那么虽然此临界区空闲,但是并不允许p1访问)

双标志先检查法(表达意愿)

表达意愿

基本思想:设置一个布尔型数组flag[],数组中各个元素用来标记各进程想要进入临界区的意愿,比如"flag[0] = true" 意味着0号进程P0现在想要进入临界区,每个进程在进入临界区之前先检查当前有没有别的进程想进入临界区,如果没有,则把自身对应的标志“flag[i]”设置为true,之后开始访问临界区

bool flag[2];      //表示进入临界区意愿的数组
flag[0] = false;   
flag[1] = false;   //初始时两进程都不想进入临界区

//P0进程
while(flag[1]);  ① //P0进程检查P1进程是否要访问临界区,如果对方不想访问就就进行②
flag[0] = true;  ② //P0进程将自己的意愿修改为true"上锁",此时P1进程就循环等待
critical section;③ //P0进程访问临界区
flag[0] = flase; ④ //P0进程完成对临界区的访问"解锁"
remainder section;

//P1进程
while(flag[0]);  ⑤ //P1进程检查P0进程是否要访问临界区,如果对方不想访问就就进行⑥
flag[1] = true;  ⑥ //P1进程将自己的意愿修改为true"上锁",此时P0进程就循环等待
critical section;⑦ //P1进程访问临界区
flag[1] = flase; ⑧ //P1进程完成对临界区的访问"解锁"
remainder section;

缺点:违反”忙则等待“原则(如果两个进程并发执行,当P0进程执行完①还未执行②时时间片用完,切换至P1进程执行⑤但是P1进程执行完⑤未执行⑥时时间片也用完,然后重新切换至P0进程执行②,此时P0进程的意愿被改变为true,然后再切换至P1进程执行⑥,此时P1进程的意愿也被改为true,然后可能暂时不发生进程切换而是进入临界区,但是P1进程在访问临界区过程中又发生了进程切换此时P0进程也进入临界区访问资源,这就会导致P0与P1进程会同时访问临界区,这是不对的)

产生原因:”检查“和”上锁“两个处理不是一气呵成的,在”检查“后”上锁“前,可能会发生进程切换

双标志后检查法(表达意愿)

表达意愿

基本思想:双标志检查法的改版,前者的问题在于是先”检查“后”上锁“,但是这样两个操作又无法一气呵成,因此导致了两个进程同时进入临界区的问题,双标志后检查法是先”上锁“后”检查“的方法来避免上述问题

bool flag[2];      //表示进入临界区意愿的数组
flag[0] = false;   
flag[1] = false;   //初始时两进程都不想进入临界区

//P0进程
flag[0] = true;  ① //P0进程将自己的意愿修改为true"上锁",此时P1进程就循环等待
while(flag[1]);  ② //P0进程检查P1进程是否要访问临界区,如果对方不想访问就就进行③
critical section;③ //P0进程访问临界区
flag[0] = flase; ④ //P0进程完成对临界区的访问"解锁"
remainder section;

//P1进程
flag[1] = true;  ⑤ //P1进程将自己的意愿修改为true"上锁",此时P0进程就循环等待
while(flag[0]);  ⑥ //P1进程检查P0进程是否要访问临界区,如果对方不想访问就就进行⑦
critical section;⑦ //P1进程访问临界区
flag[1] = flase; ⑧ //P1进程完成对临界区的访问"解锁"
remainder section;

优点:解决了”忙则等待“原则

缺点:违反了”空闲让进“和”有限等待“原则(如果由于进程切换导致要按照①⑤②⑥...的顺序执行那么两个进程都长期无法访问临界资源而产生“饥饿”现象)

Peterson算法(集大成者)

表达意愿 + 谦让

基本思想:结合单标志法、双标志的先后表示法的思想,如果双方都争着想要进入临界区,那可以让进程尝试“谦让”

bool flag[2];   //表示进入临界区意愿的数组,初始值均为false,表达“意愿”
int turn = 0;   //turn表示优先让哪个进程进入临界区,表达“谦让”

//P0进程
flag[0] = true;             ①   //主动争取,将自己的意愿改为true
turn = 1;                   ②   //主动谦让,将先优先执行进程设置为1
while(flag[1] && turn == 1);③   //检查对方食肉也想使用,且最后一次是不是自己说了“客气话”
critical section;           ④
flag[0] = false;            ⑤
remainder section;

//P1进程
flag[1] = true;             ⑥
turn = 0;                   ⑦
while(flag[0] && turn == 0);⑧
critical section;           ⑨
flag[1] = false;            ⑩
remainder section;

解释:对于一气呵成的P0进程,P0进程将自己的意愿修改为true,然后将turn修改为P1进程表示自己的谦让,然后再检查“P1进程是否想要使用并且自己也表示了谦让”如果是那么P0进程就循环等待,如果不是那么P0进程就访问临界区最后再将自己的意愿设置为false

谁最后说了“客气话”,谁就失去了行动的优先权

优点:遵循了“空闲让进”、“忙则等待”、“优先等待”三个原则(如果按照①⑥②⑦⑧③...的顺序并发的执行进程:初始turn=0,P0进程修改意愿为true,P1进程也修改意愿为true,P0进程主动谦让将turn改为1表示让P1进程先执行,然后P1进程也主动谦让将turn改为0表示让P0进程先执行,接着P1进程检查发现“P0进程有执行的意愿并且我(P1)也表示了谦让让P0进程先执行”,所以P1进程就会进入循环等待,然后P0进程检查时就会发现“P1进程虽然也有执行的意愿但是P1进程表示了谦让让我(P0)先执行”,也就是说我(P0)就可以向下单独的访问临界区,即使再次切换至P1进程也只是在循环而不会进入临界区,直到我(P0)结束访问临界区后将自己的意愿改为false,P1进程在检查时才会跳出循环区访问临界区)

缺点:未遵循“让权等待”原则(当进程无法进入临界区,就立即释放处理机资源,令该进程下CPU,但是该算法是让该进程依然位于处理机上循环等待)

本节思维导图

~over~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1349119.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

服务器的TCP连接限制:如何优化并提高服务器的并发连接数?

🌈🌈🌈🌈🌈🌈🌈🌈 欢迎关注公众号(通过文章导读关注),发送【资料】可领取 深入理解 Redis 系列文章结合电商场景讲解 Redis 使用场景、中间件系列…

Unity坦克大战开发全流程——1)需求分析

实践项目:需求分析 该游戏共有三个主要部分:UI、数据储存、核心游戏逻辑,下面我们将从开始场景、游戏场景、结束场景三个角度切入进行分析。

010、切片

除了引用,Rust还有另外一种不持有所有权的数据类型:切片(slice)。切片允许我们引用集合中某一段连续的元素序列,而不是整个集合。 考虑这样一个小问题:编写一个搜索函数,它接收字符串作为参数&a…

【代码解析】代码解析之生成token(1)

本篇文章主要解析上一篇:代码解析之登录(1)里的第8行代码调用 TokenUtils 类里的genToken 方法 https://blog.csdn.net/m0_67930426/article/details/135327553?spm1001.2014.3001.5501 genToken方法代码如下: public static S…

有了向量数据库,我们还需 SQL 数据库吗?

“除了向量数据库外,我是否还需要一个普通的 SQL 数据库?” 这是我们经常被问到的一个问题。如果除了向量数据以外,用户还有其他标量数据信息,那么其业务可能需要在进行语义相似性搜索前先根据某种条件过滤数据,例如&a…

spring创建与使用

spring创建与使用 创建 Spring 项⽬创建⼀个 Maven 项⽬添加 Spring 框架⽀持添加启动类 存储 Bean 对象创建 Bean将 Bean 注册到容器 获取并使⽤ Bean 对象创建 Spring 上下⽂获取指定的 Bean 对象获取bean对象的方法 使⽤ Bean 总结 创建 Spring 项⽬ 接下来使⽤ Maven ⽅式…

Linux:apache优化(6)—— apache的ab压力测试

要对所购买的物理机(二手)进行烧机在产品上线之前,对应用的一个压力测试对产品本身的压力测试 作用:Apache 附带了压力测试工具 ab,非常容易使用,并且完全可以模拟各种条件对 Web 服务器发起测试请求。在进行性能调整优化过程中&a…

国家开放大学形成性考核 统一考试 资料参考

试卷代号:11141 工程经济与管理 参考试题 一、单项选择题(每题2分,共20分) 1.资金的时间价值( )。 A.现在拥有的资金在将来投资时所能获得的利益 B.现在拥有的资金在将来消费时所付出的福利损失 C.…

C练习——银行存款

题目:设银行定期存款的年利率 rate为2.25%,已知存款期为n年,存款本金为capital 元,试编程计算并输出n年后本利之和deposit。 解析:利息本金*利率,下一年的本金又是是今年的本利之和 逻辑:注意浮点数,导入…

计算机操作系统(OS)——P5设备管理

1、I/O设备的概念和分类 什么是I/O设备 I/O就是输入/输出(Input/Output)。 I/O设备就是可以将数据输入到计算机,或者可以接收计算机输出数据的外部设备,属于计算机中的硬件部件。 UNIX系统将外部设备抽象为一种特殊的文件&#x…

Vue:使用IDEA开发Vue的相关配置

一、IDEA无法识别.vue文件 1、IDEA 添加Vue插件 2、添加Vue配置 File | Settings | Editor | File Types 找到 HTML 文件 在下面点号 输入*.vue 二、IDEA无法创建.vue文件 1、问题 在开发过程中,发现创建文件的界面,没有vue模板 2、相关配置 Fi…

PAT乙级1045 快速排序

著名的快速排序算法里有一个经典的划分过程:我们通常采用某种方法取一个元素作为主元,通过交换,把比主元小的元素放到它的左边,比主元大的元素放到它的右边。 给定划分后的 N 个互不相同的正整数的排列,请问有多少个元…

苦心分享两款免费AI 绘图软件,效果真的不错

这里写自定义目录标题 图一是 AI 绘画软件一键抠图做的,软件还免费 网址:https://www.yijiankoutu.com/ 一个非常强大的AI绘画网站,能够免费生成各种好看的二次元、3D、国风、漫画、卡通等风格的图片,生成图片跟文字匹配度非常高,…

2023/12/30 c++ work

定义一个Person类,私有成员int age,string &name,定义一个Stu类,包含私有成员double *score,写出两个类的构造函数、析构函数、拷贝构造和拷贝赋值函数,完成对Person的运算符重载(算术运算符、条件运算…

Go语言实战:如何使用Timeout Context优雅地取消任务

Go语言实战:如何使用Timeout Context优雅地取消任务 引言Go语言和并发编程简介什么是ContextTimeout Context的原理实战演示最佳实践和注意事项总结 引言 在现代软件开发中,尤其是在处理高并发系统时,正确地管理和取消正在进行的任务成为一项…

5个用于构建Web应用程序的Go Web框架

探索高效Web开发的顶级Go框架 Go(或称为Golang)以其简洁性、高效性和出色的标准库而闻名。然而,有几个流行的Go Web框架和库为构建Web应用程序提供了额外的功能。以下是五个最值得注意的Go框架: 1. Gin: Gin是一个高…

【致远OA】按人员编码获取所有待办事项

接口说明 按人员编码获取所有待办事项 兼容版本 since V7.0 请求方式 http请求方式:GET http://ip:port/seeyon/rest/affairs/pending/code/{memberCode} 如 http://127.0.0.1/seeyon/rest/affairs/pending/code/9981 效果参考 响应结果 参考对象实例&#x…

ROS TF坐标变换 - 动态坐标变换

目录 一、动态坐标变换(C实现)二、动态坐标变换(Python实现) 一、动态坐标变换(C实现) 所谓动态坐标变换,是指两个坐标系之间的相对位置是变化的。比如机械臂末端执行器与 base_link 之间&…

在Go中使用Goroutines和Channels发送电子邮件

学习如何使用Goroutines和Channels在Go中发送电子邮件 在现代软件开发的世界中,通信是一个关键元素。发送电子邮件是各种目的的常见实践,例如用户通知、报告等。Go是一种静态类型和编译语言,为处理此类任务提供了高效和并发的方式。在本文中&…

OSG读取和添加节点学习

之前加载了一个模型,代码是, osg::Group* root new osg::Group(); osg::Node* node new osg::Node(); node osgDB::readNodeFile("tree.osg"); root->addChild(node); root是指向osg::Group的指针; node是 osg:…