大话操作系统(12)经典同步问题

经典同步问题

哲学家就餐问题

先来看看哲学家就餐的问题描述:

5 个⽼⼤哥哲学家,闲着没事做,围绕着⼀张圆桌吃⾯;
巧就巧在,这个桌⼦只有 5 ⽀叉⼦,每两个哲学家之间放⼀⽀叉⼦;
哲学家围在⼀起先思考,思考中途饿了就会想进餐;
奇葩的是,这些哲学家要两⽀叉⼦才愿意吃⾯,也就是需要拿到左右两边的叉⼦才进餐;
吃完后,会把两⽀叉⼦放回原处,继续思考;
在这里插入图片描述

那么问题来了,如何保证哲 学家们的动作有序进⾏,⽽不会出现有⼈永远拿不到叉⼦呢?

方案一

我们⽤信号量的⽅式,也就是 PV 操作来尝试解决它,代码如下:
在这里插入图片描述

上⾯的程序,好似很⾃然。拿起叉⼦⽤ P 操作,代表有叉⼦就直接⽤,没有叉⼦时就等待其他哲学家放回叉⼦。

不过,这种解法存在⼀个极端的问题:假设五位哲学家同时拿起左边的叉⼦,桌⾯上就没有叉⼦了,这样就没有⼈能够拿到他们右边的叉⼦,也就说每⼀位哲学家都会在 P(fork[(i + 1) % N ]) 这条语句阻塞了,很明显这发⽣了死锁的现象。

方案二

既然「⽅案⼀」会发⽣同时竞争左边叉⼦导致死锁的现象,那么我们就在拿叉⼦前,加个互斥信号量,代码如下:
在这里插入图片描述

上⾯程序中的互斥信号量的作⽤就在于,只要有⼀个哲学家进⼊了「临界区」,也就是准备要拿叉⼦时,其他哲学家都不能动,只有这位哲学家⽤完叉⼦了,才能轮到下⼀个哲学家进餐。

⽅案⼆虽然能让哲学家们按顺序吃饭,但是每次进餐只能有⼀位哲学家,⽽桌⾯上是有 5 把叉⼦,按道理是能可以有两个哲学家同时进餐的,所以从效率⻆度上,这不是最好的解决⽅案。

方案三

那既然⽅案⼆使⽤互斥信号量,会导致只能允许⼀个哲学家就餐,那么我们就不⽤它。

另外,⽅案⼀的问题在于,会出现所有哲学家同时拿左边⼑叉的可能性,那我们就避免哲学家可以同时拿左边的⼑叉,采⽤分⽀结构,根据哲学家的编号的不同,⽽采取不同的动作。

即让偶数编号的哲学家「先拿左边的叉⼦后拿右边的叉⼦」,奇数编号的哲学家「先拿右边的叉⼦后拿左边的叉⼦」。
在这里插入图片描述
上⾯的程序,在 P 操作时,根据哲学家的编号不同,拿起左右两边叉⼦的顺序不同。另外,V 操作是不需要分⽀的,因为 V 操作是不会阻塞的。

⽅案三即不会出现死锁,也可以两⼈同时进餐。

方案四

在这⾥再提出另外⼀种可⾏的解决⽅案,我们⽤⼀个数组 state 来记录每⼀位哲学家在进程、思考还是饥饿状态(正在试图拿叉⼦)。

那么,⼀个哲学家只有在两个邻居都没有进餐时,才可以进⼊进餐状态。

第 i 个哲学家的左邻右舍,则由宏 LEFT 和 RIGHT 定义:
LEFT : ( i + 5 - 1 ) % 5
RIGHT : ( i + 1 ) % 5

⽐如 i 为 2,则 LEFT 为 1, RIGHT 为 3。
具体代码实现如下:
在这里插入图片描述
上⾯的程序使⽤了⼀个信号量数组,每个信号量对应⼀位哲学家,这样在所需的叉⼦被占⽤时,想进餐的哲学家就被阻塞。

注意,每个进程/线程将 smart_person 函数作为主代码运⾏,⽽其他 take_forks 、 put_forks 和test 只是普通的函数,⽽⾮单独的进程/线程。

⽅案四同样不会出现死锁,也可以两⼈同时进餐。

读者-写者问题

前⾯的「哲学家进餐问题」对于互斥访问有限的竞争问题(如 I/O 设备)⼀类的建模过程⼗分有⽤。

另外,还有个著名的问题是「读者-写者」,它为数据库访问建⽴了⼀个模型。

读者只会读取数据,不会修改数据,⽽写者即可以读也可以修改数据。

读者-写者的问题描述:
「读-读」允许:同⼀时刻,允许多个读者同时读
「读-写」互斥:没有写者时读者才能读,没有读者时写者才能写
「写-写」互斥:没有其他写者时,写者才能写

接下来,提出⼏个解决⽅案来分析分析。

方案一:读者优先

使⽤信号量的⽅式来尝试解决:

信号量 wMutex :控制写操作的互斥信号量,初始值为 1 ;
读者计数 rCount :正在进⾏读操作的读者个数,初始化为 0;
信号量 rCountMutex :控制对 rCount 读者计数器的互斥修改,初始值为 1;

接下来看看代码的实现:
在这里插入图片描述
上⾯的这种实现,是读者优先的策略,因为只要有读者正在读的状态,后来的读者都可以直接进⼊,如果读者持续不断进⼊,则写者会处于饥饿状态。

方案二:写者优先

那既然有读者优先策略,⾃然也有写者优先策略:

只要有写者准备要写⼊,写者应尽快执⾏写操作,后来的读者就必须阻塞;
如果有写者持续不断写⼊,则读者就处于饥饿;

在⽅案⼀的基础上新增如下变量:

信号量 rMutex :控制读者进⼊的互斥信号量,初始值为 1;
信号量 wDataMutex :控制写者写操作的互斥信号量,初始值为 1;
写者计数 wCount :记录写者数量,初始值为 0;
信号量 wCountMutex :控制 wCount 互斥修改,初始值为 1;

具体实现如下代码:
在这里插入图片描述
注意,这⾥ rMutex 的作⽤,开始有多个读者读数据,它们全部进⼊读者队列,此时来了⼀个写者,执⾏了 P(rMutex) 之后,后续的读者由于阻塞在 rMutex 上,都不能再进⼊读者队列,⽽写者到来,则可以全部进⼊写者队列,因此保证了写者优先。

同时,第⼀个写者执⾏了 P(rMutex) 之后,也不能⻢上开始写,必须等到所有进⼊读者队列的读者都执⾏完读操作,通过 V(wDataMutex) 唤醒写者的写操作。

⽅案三:公平策略

既然读者优先策略和写者优先策略都会造成饥饿的现象,那么我们就来实现⼀下公平策略。

公平策略:
优先级相同;
写者、读者互斥访问;
只能⼀个写者访问临界区;
可以有多个读者同时访问临街资源;

具体代码实现:
在这里插入图片描述
看完代码不知你是否有这样的疑问,为什么加了⼀个信号量 flag ,就实现了公平竞争?

对⽐⽅案⼀的读者优先策略,可以发现,读者优先中只要后续有读者到达,读者就可以进⼊读者队列, ⽽写者必须等待,直到没有读者到达。
没有读者到达会导致读者队列为空,即 rCount==0 ,此时写者才可以进⼊临界区执⾏写操作。

⽽这⾥ flag 的作⽤就是阻⽌读者的这种特殊权限(特殊权限是只要读者到达,就可以进⼊读者队列)。

⽐如:开始来了⼀些读者读数据,它们全部进⼊读者队列,此时来了⼀个写者,执⾏ P(flag) 操作,使得后续到来的读者都阻塞在 flag 上,不能进⼊读者队列,这会使得读者队列逐渐为空,即 rCount 减为0。

这个写者也不能⽴⻢开始写(因为此时读者队列不为空),会阻塞在信号量 wDataMutex 上,读者队列中的读者全部读取结束后,最后⼀个读者进程执⾏ V(wDataMutex) ,唤醒刚才的写者,写者则继续开始进⾏写操作。

学自小林coding,侵删

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 《大话信号与系统》是一本关于信号与系统的入门书籍。它简单易懂地介绍了信号与系统的基本概念、数学表示、线性时不变系统、时域分析、频域分析等一系列重要内容。本书被广泛应用于电子、通信、计算机等领域,特别适合初学者学习信号与系统。 这本书不仅理论脉络连贯,而且知识点丰富。本书约定了统一的符号和术语,使学习者更好地理解主要概念。此外,本书还包含大量的例题和仿真案例,帮助学习者检验理解情况,深入理解和掌握知识点。 此外,本书还尤其强调“概念难点重难点”和重视分析思维的重要性,让初学者可以更好地把握信号与系统的核心。这些特征都是使《大话信号与系统》成为初学者推荐的主要原因之一。总之,如果你是初学者入门信号与系统,那么这本书无疑是个不错的选择。 ### 回答2: 大话信号与系统是一本介绍信号与系统基础知识的入门教材,可以让读者初步了解信号与系统的定义、特性和变换等方面的知识。本书内容丰富,易于理解,适合初学者阅读。该书主要分为三大部分:信号基础、系统基础和信号分析与处理。信号基础介绍了信号的基本概念、分类、特性以及常见的信号,比如周期信号、非周期信号等。系统基础重点介绍了系统的性质、线性系统、时不变系统和卷积等知识点。信号分析与处理部分介绍了信号的傅里叶变换及其在信号分析和处理中的应用,还讲述了数字信号处理、滤波器、抽样等实用技术。本书的内容简洁明了,注重实际应用,非常适合需要了解信号与系统方面知识的初学者学习使用。同时,还需要注意的是,本书主要是介绍理论知识,并没有太多的工程实践内容,如果需要深入了解实际应用,需要参考其他专业书籍。 ### 回答3: 《大话信号与系统》是一本以通俗易懂的方式讲解信号与系统基础知识的书籍,作者是学者卢炜航。这本书分为七章,从信号与系统基础开始介绍,逐渐深入到频率响应和滤波器、离散信号与系统等内容。此外,书中包含了很多实例和应用场景,如噪声降噪、音频处理等,帮助读者更好地理解和应用知识。 书中的主要内容包括:信号的分类和基本概念、系统的分类和基本概念、傅里叶变换和频域分析、卷积、滤波器、采样和离散信号处理等。 书中的语言通俗易懂,内容深入浅出,对没有专业背景但想要学习信号与系统的读者很有帮助。并且,此书注重实用性,将学习到的知识应用到具体的实例中,帮助读者更好地理解和应用知识。 总之,《大话信号与系统》是一本值得阅读的书籍。对于需要学习信号与系统的初学者或非专业人士,这是一本易于理解的入门读物。同时,这本书还可作为工程技术人员的一本参考书,在实际应用中进行进一步的学习和应用。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海岸星的清风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值