操作系统——经典同步问题

1、概念

1.1 进程同步与互斥

在多道程序环境下,进程是并发执行的(并发执行是指两个或多个事件在某段时间间隔内并发),不同进程之间存在着不同的相互制约关系。为了协调进程之间的相互制约关系,引入了进程同步的概念。

进程同步是直接制约关系,指为完成某种任务而建立的两个或多个进程,这些进程因为需要在某些位置上协调他们的工作次序而等待、传递信息所产生的的制约关系。(源于他们之间的互相合作关系)

进程互斥是间接制约关系,当一个进程进入临界区使用临界资源时,另一个进程必须等待,当占用临界资源的进程退出临界区时,另一个进程才允许去访问此临界资源。

临界资源是一次仅允许一个进程使用的资源,临界资源的访问过程:进入区(在进入区要检查可否进入临界区,并设置正在访问临界区的标识,以阻止其他进程同时进入),临界区,退出区,剩余区

临界区是访问临界临界资源的那段代码

同步机制准则:

空闲让进:临界区空闲时,可以允许一个请求进入临界区的进程立即进入临界区

忙则等待:当已有进程进入临界区时,其他试图进入临界区的进程必须等待

有限等待:对请求访问的进程,应保证能在有限时间内进入临界区

让权等待:当进程不能进入临界区时,应立即释放处理器,防止进程忙等待

1.2 信号量

信号量是一种功能较强的机制,可以用来解决互斥与同步的问题,它只能被两个标准的原语操作,即为“P”和“V”操作,P操作是信号量减1,V操作是信号量加1

原语是指完成某种功能且不被分割、不被中断执行的操作序列

(1)整型信号量

整型信号量是来表示资源数目的整形量S,只要S≤0,就会不断测试,并未遵循“让权等待”的准则,而是使进程处于“忙等”状态。

P(S){while(S<=0){S = S-1}
}V(S){S=S+1
}

(2)记录型信号量

记录型信号量机制是一种不存在“忙等”现象的进程同步机制,除了表示资源数目的整型变量S外,再增加一个进程链表L,用于链接所有等待该资源的进程。

//定义结构体
typedef struct{int S;struct process *L;
}semaphore;void P(semaphore se){se.S--;if(se.S<0){add this process to se;block(se); //调用block原语,进行自我阻塞}
}void V(semaphore se){se.S++if (se.S<=0){remove a process P from se;wakeup(P); //调用wakeup原语,唤醒链表中的第一个等待进程}
}

(3)分析进程同步和互斥问题的方法步骤

  • 关系分析:找出问题中的进程数,并分析他们之间的同步和互斥关系
  • 整理思路:找出解决问题的关键点,并且根据做过的题目找出解决思路,根据进程的操作流程确定P操作,V操作的大致顺序
  • 设置信号量:设置需要的信号量,确定处置,完善整理

(4)利用信号量实现进程同步

问题描述:S为P1、P2两个进程的公共信号量,初始值为0,进程P2执行需要依赖进程P1中语句x的运行结果,即只有当语句x执行完成之后,语句y才可以执行。

semaphore S=0;P1(){x; //先执行xV(S);  //s++
}P2(){P(x);y ;V(y);}

(5)利用信号量实现互斥

问题描述:设S为实现进程P1、P2互斥的信号量,由于每次只允许一个进程进入临界区,设置S=1(即可用资源数为1),当进程对信号量S进行P操作后进入临界区,并在退出后,该进程对该信号量执行V操作,表示没有进程进入临界区,可以让其他进程进入。设计如下:

semaphore S=1;P1(){P(S); //访问临界资源,S--//进入临界区V(S);//访问结束,S++
}
P2(){P(S); //访问临界资源,S--//进入临界区V(S);//访问结束,S++
}

2、经典问题

2.1 生产者-消费者

  • 问题描述:一组生产者进程和一组消费者进程共享一个初始为空、大小为n的缓冲区,只有缓冲区没满时,生产者才能把消息放入到缓冲区,否则必须等待;只有缓冲区不空时,消费者才能从中取出消息,否则必须等待。由于缓冲区是临界资源,它只允许一个生产者放入消息,或者一个消费者从中取出消息。
  • 问题分析:

(1)关系分析:生产者和消费者对缓冲区访问是互斥,生产者和消费者又是相互协作关系,生产者生产之后才能消费,属于同步关系

(2)整理思路:只有生产者和消费者两个进程,两个进程间存在着同步和互斥关系,要解决互斥和同步PV操作的位置

(3)信号量设置:信号量mutex作为互斥信号量,它用于控制互斥访问缓冲池,互斥信号量初值为1;信号量full用于记录当前缓冲池中“满”缓冲区数,初值为0。信号量empty 用于记录当前缓冲池中“空”缓冲区数,初值为n。

#define semaphore intsemaphore empty=n; //表示空缓冲区的个数
semaphore full=0; //表示满缓冲区的个数semaphore mutex =1; //互斥信号量(生产者和消费者共用缓冲区)void Producer(){while(1) {produce a item; //生产数据P(empty); //空缓冲区的个数减1P(mutex); //互斥变量减1,进入临界区add  item to buffer; // 将item放入缓冲区V(mutex);  //互斥量加1,退出临界区V(full);   //满缓冲区加1}
}
void Consumer(){P(full); // 同步,判断缓冲区是否有生产者P(mutex); //互斥变量减1,进入临界区remove item from buffer; //将item移除缓冲区V(mutex); //互斥量加1,退出临界区V(empty); //空缓冲区加1consumer a item; //消费数据
}

2.2 分水果问题

  • 问题描述:桌子上有一个盘子,每次只能想其中放入一个水果,爸爸专向盘子中放苹果,妈妈专向盘子中放橘子,儿子专等吃盘子中的橘子,女儿专等吃盘子中的苹果。只有盘子为空时,爸爸或妈妈就可向盘子中放一个水果;仅当盘子中有自己需要的水果时,儿子或女儿可以从盘子中取出。
  • 问题分析:

(1)关系分析。这里的关系稍复杂一些,首先由每次只能向其中放入一只水果可知爸爸和妈妈是互斥关系。爸爸和女儿、妈妈和儿子是同步关系,而且这两对进程必须连起来,儿子和女儿之间没有互斥和同步关系,因为他们是选择条件执行,不可能并发

(2)整理思路。这里有4个进程,实际上可以抽象为两个生产者和两个消费者被连接到大小为1的缓冲区上

(3) 信号量设置。首先设置信号量plate为互斥信号量,表示是否允许向盘子放入水果,初值为1,表示允许放入,且只允许放入一个。信号量 apple表示盘子中是否有苹果,初值为0,表示盘子为空,不许取,若apple=1可以取。信号量orange表示盘子中是否有橘子,初值为0,表示盘子为空,不许取,若orange=1可以取。

notes:生产者和消费者是生产者生产完把缓冲区释放,消费者再去访问缓冲区;分水果是放完水果,标记盘子有水果,才会去拿水果,再释放盘子。

#define semaphore int
semaphore plate=1;  //互斥
semaphore apple=0;
semaphore orange=0;void dad(){while(1){//prepare an appleP(plate);put the apple on the plate;V(apple);  //apple标记为1,证明盘子有apple}
}void mom(){while(1){//prepare an orangeP(plate);put the orange on the plate;V(orange);  //orange标记为1,证明盘子有orange}
}void daughter(){while(1){P(apple) take an apple from the plate;V(plate);  //plate标记为1,证明可以放水果了eat the apple;}
}void son(){while(1){P(orange) take an orange from the plate;V(plate);  //plate标记为1,证明可以放水果了eat the orange;}
}

2.3 读者和写者问题

  • 问题描述:有读者和写者两组并发进程,共享一个文件,当两个或以上的读进程同时访问共享数据时不会产生副作用,但若某个写进程和其他进程(读进程或写进程)同时访问共享数据时则可能导致数据不一致的错误。因此要求:①允许多个读者可以同时对文件执行读操作;②只允许一个写者往文件中写信息;③任一写者在完成写操作之前不允许其他读者或写者工作;④写者执行写操作前,应让已有的读者和写者全部退出。
  • 问题分析

(1)关系分析:有两个进程:读者进程和写者进程,写者和读者、写者和写者都是互斥的,读者和读者是同步关系(依次访问,依次退出),可以同时有多个读者在读

(2)整理思路:写者是跟任何进程互斥,用PV可以解决,读者比较复杂,除了实现与写者的互斥,还要实现与其他读者的同步,设计了一个计数器来判断当前是否有读者读文件,同时,不同读者对计数器的访问也应该是互斥的

(3)信号量设置:首先设置信号量count为计数器,用来记录当前读者数量,初值为0; 设置rmutex为互斥信号量,用于保护更新count变量时的互斥;设置互斥信号量rw用于保证读者和写者的互斥访问。

#define semaphore int
semaphore rmutex=1; //读者之间(依次访问和退出)的互斥量
semaphore wmutex=1; //写者和读者的互斥量
int count=0; //统计读者的数量void reader(){while(1){P(rmutex)if(count==0) P(wmutex); //count==0 意味着没有读者在读文件,可以写文件,先进行加锁count++;V(rmutex)reading; //读者进入之后,进行写文件P(mutex);count--;if(count==0)V(wmutex); //count==0证明读者已经读完退出文件,可以写,并将互斥量解锁V(rmutex); //释放互斥变量}
}void writer(){while(1){P(wmutex);writing;V(wmutex);}
}

2.4 哲学家进餐(死锁)

  • 问题描述:一张圆桌上坐着5名哲学家,每两个哲学家之间的桌上摆一根筷子,桌子的中间是一碗米饭,如图2-10所示。哲学家们倾注毕生精力用于思考和进餐,哲学家在思考时,并不影响他人。只有当哲学家饥饿的时候,才试图拿起左、 右两根筷子(一根一根地拿起)。如果筷子已在他人手上,则需等待。饥饿的哲学家只有同时拿到了两根筷子才可以开始进餐,当进餐完毕后,放下筷子继续思考。
  • 补充:饥饿和死锁的定义

“饥饿”并不表示系统一定死锁,但至少有一个进程的执行被无限期推迟。“饥饿”与死锁的主要差别有:

(1)进入“饥饿”状态的进程可以只有一个,而由于循环等待条件而进入死锁状态的进程却必须大于或等于两个。

(2)处于“饥饿”状态的进程可以是一个就绪进程,如静态优先权调度算法时的低优先权进程,而处于死锁状态的进程则必定是阻塞进程。

  • 问题分析:

(1)关系分析:5个哲学家和左右邻居对其中间的筷子访问是互斥关系

(2)整理思路:本题的关键是如何让一个哲学家拿到左右两个筷子而不造成死锁或者饥饿现象。那么解决方法有两个,一个是让他们同时拿两个筷子;二是对每个哲学家的动作制定规则,避免饥饿或者死锁现象的发生。

(3)信号量设置:定义互斥信号量数组chopstick[5] = {l, 1, 1, 1, 1}用于对5个筷子的互斥访问。对哲学家按顺序从0~4编号,哲学家i左边的筷子编号为i,哲学家右边的筷子编号(i+1)%5。(同时拿两边的筷子)

#define semaphore int
semaphore chopstick[5]={1,1,1,1,1}Pi(){while(1){P(chopstick[i]);  //拿左筷子P(chopstick[(i+1)%5]);   //拿右筷子eat; //进餐V(chopstick[i]);  //放下左筷子V(chopstick[(i+1)%5]);   //放下右筷子think; //思考}}

该算法存在以下问题:当五个哲学家都想要进餐,分别拿起他们左边筷子的时候(都恰好执行完P(chopstick[i]);)筷子已经被拿光了,等到他们再想拿右边的筷子的时候(执行 P(chopstick[(i+l)%5]);)就全被阻塞了,这就出现了死锁。

为了防止死锁的发生,可以对哲学家进程施加一些限制条件,比如至多允许四个哲学家同时进餐;仅当一个哲学家左右两边的筷子都可用时才允许他抓起筷子;对哲学家顺序编号,要求奇数号哲学家先抓左边的筷子,然后再转他右边的筷子,而偶数号哲学家刚好相反。正解制定规则如下:假设釆用第二种方法,当一个哲学家左右两边的筷子都可用时,才允许他抓起筷子。

semaphore chopstick[5] = {1,1,1,1,1}; //初始化信号量
semaphore mutex=l;  //设置取筷子的信号量
Pi(){ //i号哲学家的进程while(1){P (mutex) ; //在取筷子前获得互斥量P (chopstick [i]) ; //取左边筷子P (chopstick[ (i+1) %5]) ;  //取右边筷子V (mutex) ; //释放取筷子的信号量eat;  //进餐V(chopstick[i] ) ;  //放回左边筷子V(chopstick[ (i+l)%5]) ;  //放回右边筷子think;  // 思考}
}

参考内容:

信号量:整型、记录型信号量以及利用信号量实现进程互斥和前驱关系_C语言中文网

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

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

相关文章

JavaScript权威指南(第5版)pdf

下载地址&#xff1a;网盘下载内容简介编辑第5版针对Ajax和Web 2.0技术进行了全新的改版。和上一版相比&#xff0c;更新的内容较多&#xff0c;总体上接近整个篇幅的1/2&#xff0c;而这也正是本书姗姗来迟的原因之一。具体来说&#xff0c;第5版在以下部分有所更新&#xff1…

操作系统——死锁(银行家算法)

1、概述 1.1 死锁 死锁是多个进程因竞争资源而造成的一种僵局&#xff08;互相等待&#xff09;&#xff0c;若无外力作用&#xff0c;这些进程都将无法向前推进。 1.2 死锁产生的原因和条件 原因&#xff1a;&#xff08;1&#xff09;竞争资源&#xff1b;&#xff08;2&…

STM32——库函数开发小结

STM32——库函数开发小结 宗旨&#xff1a;技术的学习是有限的&#xff0c;分享的精神是无限的。 基本上所有外设都有以下几类寄存器&#xff1a;【CR/DR/SR】 &#xff08;1&#xff09;控制寄存器 xxx_CR(Control/Configuration Register)&#xff1a;这类寄存器是用来配置…

过年不回家,难受不

看电视&#xff0c;特别怕看到离别的情节&#xff0c;最近看「山海情」&#xff0c;也刚好看到。本着剧情不透露原则&#xff0c;我就不说里面的内容了。小时候&#xff0c;经历的都只能算是小别离了。小时候喜欢去外婆家&#xff0c;在外婆家不用干繁重的农活&#xff0c;父母…

lodap问题集锦

1、分页打印时&#xff0c;同一行显示在不同页内 &#xff0c;调整行分页粒度 LODOP.SET_PRINT_STYLEA(0, "TableRowThickNess", 40); 转载于:https://www.cnblogs.com/feihusurfer/p/8482180.html

系统管理员节日 网民的感恩日

11月8日 “记者节"、 9月10日“教师节”、 5月12日“国际护士节”&#xff0c;职业节日的设立会提升公众对该职业的关注程度&#xff0c;该职业的形象也往往因节日而凸显&#xff0c;而作为让这个世界变平的&#xff0c;在幕后默默付出的系统管理者的心声又有谁听到了呢&a…

操作系统——内存管理

1、内存基本概念 1.1 主要功能 内存空间的分配与回收&#xff1b;地址转换内存保护&#xff1a;使用上下限寄存器或者重定位寄存器和界地址寄存器内存扩充&#xff1a;交换和覆盖内容共享 2、内存的分配与回收 2.1 连续分配方式 连续分配方式是指为一个用户程序分配一个连续…

解决一个驱动代码解耦合问题

之前解决的项目LCD设备兼容问题&#xff0c;在 a.c 文件里面定义了一个变量&#xff0c;然后在 b.c 里面使用 extern声明引用这个变量&#xff0c;通过这种方法可以在b.c中使用在a.c 里面初始化的变量。但是这中情况就会引起一个问题&#xff0c;就是驱动代码之间耦合了&#x…

STM32——DMA

STM32——DMA 宗旨&#xff1a;技术的学习是有限的&#xff0c;分享的精神是无限的。 DMA 是为CPU分担数据转移的工作。因为DMA的存在CPU才被解放出来&#xff0c;它可以在 DMA 转移数据的过程中同时进行数据运算、响应中断&#xff0c;大大提高效率。 1、DMA工作分析 数据传…

YOLOv8改进 | 主干篇 | 利用SENetV1改进网络结构 (ILSVRC冠军得主)

一、本文介绍 本文给大家带来的改进机制是SENet&#xff08;Squeeze-and-Excitation Networks&#xff09;其是一种通过调整卷积网络中的通道关系来提升性能的网络结构。SENet并不是一个独立的网络模型&#xff0c;而是一个可以和现有的任何一个模型相结合的模块(可以看作是一…

如何进入保护模式?

IA-32为操作系统及其软件的发展提供了大量的支持&#xff0c;它提供了4种操作模式&#xff1a; 1,Real Mode,汇编书中的实模式&#xff0c;工作方式相当于8086。 2,Protected Mode,保护模式&#xff0c;提供支持多任务环境的工作形式。 3,Virtual 8086 Mode,虚拟8086模式&#…

搭建Servlet在线视频

这个视频flash上传及在线播放&#xff0c;搞了我一天了&#xff0c;总算有点成果&#xff0c;但还有一些疑问没有解决&#xff0c;现在发这篇随笔&#xff0c;为的就是交流视频在线上传和观看的一些问题。 在线编辑器使用FCKEditor&#xff0c;首先是修改FCKEditor的配置文件&a…

操作系统——内存管理例题

1、关于分配策略例题 case1&#xff1a;某系统的空闲分区见下表&#xff0c;如有下列作业&#xff1a;96KB&#xff0c;20KB&#xff0c;200KB&#xff0c;分别采用首次适应算法和最佳适应算法来处理这些作业序列&#xff0c;哪种算法能满足该作业序列请求&#xff1f; 分区号…

STM32中C语言知识点:初学者必看,老鸟复习(长文总结)

说在前面的话一位初学单片机的小伙伴让我推荐C语言书籍&#xff0c;因为C语言基础比较差&#xff0c;想把C语言重新学一遍&#xff0c;再去学单片机&#xff0c;我以前刚学单片机的时候也有这样子的想法。其实C语言是可以边学单片机边学的&#xff0c;学单片机的一些例程中&…

STM32——ADC

STM32——ADC 宗旨&#xff1a;技术的学习是有限的&#xff0c;分享的精神是无限的。 一、ADC指标 有 18 个通道&#xff0c;可测量 16 个外部和 2 个内部信号源。各通道的 A/D 转换可以单次、连续、扫描或间断模式执行 &#xff1b;ADC的结果可以左对齐或右对齐方式存储在 16…

时间复杂度和空间复杂度,一看就懂,面试前必过一遍

一、定义时间和空间是程序的一个硬性指标&#xff0c;一个用来衡量 代码执行的速度 &#xff0c;一个用来衡量 存储空间的大小程序 数据结构 算法时间复杂度&#xff1a;就是执行程序的快慢&#xff0c;速度越快&#xff0c;时间复杂度就越好。空间复杂度&#xff1a;就是执…

Oracle数据库自动存储管理(ASM)

关于ASM的讨论很多&#xff0c;但是到底什么是ASM?ASM是一个有效的抽象层&#xff0c;使你的Oracle数据库可以与叫做diskgroups的抽象空间一起使用&#xff0c;而不是直接使用datafiles。这带来了很多好处&#xff0c;但是也要求学习一些新的概念、命令、使用和管理任务。所以…

数据结构——排序【仅用于考试】

1、简介 排序&#xff0c;是重新排列表中的元素&#xff0c;使表中的元素满足按关键字有序的过程 稳定性&#xff1a;选取两个元素Ri<Rj&#xff0c;经过排序算法之后&#xff0c;仍为Ri<Rj 不稳定的排序&#xff1a;【简单选择排序&#xff0c;快速排序&#xff0c;堆…

[UWP]做个调皮的BusyIndicator

1. 前言 最近突然想要个BusyIndicator。做过WPF开发的程序员对BusyIndicator应该不陌生&#xff0c;Extended WPF Toolkit 提供了BusyIndicator的开源实现&#xff0c;Silverlight Toolkit也有一个&#xff0c;这次想要把这个控件移植到UWP中。 2. 先说点正经的 2.1 BusyIndica…