操作系统的信号量和管程

2024-04-02 13:58

本文主要是介绍操作系统的信号量和管程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

信号量 semaphore
信号量是操作系统提供的一种协调共享资源访问的方法
软件同步是平等线程间的一种同步协商机制
OS是管理者,地位高于进程
用信号量表示系统资源的数量

由一个整形 (sem)变量和两个原子操作组成
P()(Prolaag (荷兰语尝试减少))
sem减1
如sem<0, 进入等待, 否则继续
V()(Verhoog (荷兰语增加))
sem加1
如sem≤0,唤醒一个等待进程

P() 可能阻塞,V()不会阻塞,这些只能在内核实现,而不能在用户实现。

信号量的使用:
(1) 同步 线程间的事件等待
(2) 互斥 临界区的互斥访问控制
用信号量实现临界区的互斥访问必须成对使用P,V操作 ,不能次序错误、重复或者遗漏

条件同步:初值设为0

自旋锁不能实现先进先出:
它是为实现保护共享资源而提出一种锁机制。其实,自旋锁与互斥锁比较类似,它们都是为了解决对某项资源的互斥使用。无论是互斥锁,还是自旋锁,在任何时刻,最多只能有一个保持者,也就说,在任何时刻最多只能有一个执行单元获得锁。但是两者在调度机制上略有不同。对于互斥锁,如果资源已经被占用,资源申请者只能进入睡眠状态。但是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁,”自旋”一词就是因此而得名。
跟互斥锁一样,一个执行单元要想访问被自旋锁保护的共享资源,必须先得到锁,在访问完共享资源后,必须释放锁。如果在获取自旋锁时,没有任何执行单元保持该锁,那么将立即得到锁;如果在获取自旋锁时锁已经有保持者,那么获取锁操作将自旋在那里,直到该自旋锁的保持者释放了锁。由此我们可以看出,自旋锁是一种比较低级的保护数据结构或代码片段的原始方式,这种锁可能存在两个问题:
死锁。试图递归地获得自旋锁必然会引起死锁:递归程序的持有实例在第二个实例循环,以试图获得相同自旋锁时,不会释放此自旋锁。在递归程序中使用自旋锁应遵守下列策略:递归程序决不能在持有自旋锁时调用它自己,也决不能在递归调用时试图获得相同的自旋锁。此外如果一个进程已经将资源锁定,那么,即使其它申请这个资源的进程不停地疯狂“自旋”,也无法获得资源,从而进入死循环。
过多占用cpu资源。如果不加限制,由于申请者一直在循环等待,因此自旋锁在锁定的时候,如果不成功,不会睡眠,会持续的尝试,单cpu的时候自旋锁会让其它process动不了. 因此,一般自旋锁实现会有一个参数限定最多持续尝试次数. 超出后, 自旋锁放弃当前time slice. 等下一次机会
由此可见,自旋锁比较适用于锁使用者保持锁时间比较短的情况。正是由于自旋锁使用者一般保持锁时间非常短,因此选择自旋而不是睡眠是非常必要的,自旋锁的效率远高于互斥锁。信号量和读写信号量适合于保持时间较长的情况,它们会导致调用者睡眠,因此只能在进程上下文使用,而自旋锁适合于保持时间非常短的情况,它可以在任何上下文使用。如果被保护的共享资源只在进程上下文访问,使用信号量保护该共享资源非常合适,如果对共享资源的访问时间非常短,自旋锁也可以。但是如果被保护的共享资源需要在中断上下文访问(包括底半部即中断处理句柄和顶半部即软中断),就必须使用自旋锁。自旋锁保持期间是抢占失效的,而信号量和读写信号量保持期间是可以被抢占的。自旋锁只有在内核可抢占或SMP(多处理器)的情况下才真正需要,在单CPU且不可抢占的内核下,自旋锁的所有操作都是空操作,

与前面的区别 P,V代码的原子性由操作系统保护。

必须成对使用P,V
如果不申请(P操作),直接V操作:就会有多个线程进入到临界区
如果申请了(P不操作),不释放(V):谁都不能进入临界区

不能避免死锁的出现,必须在写程序的时候解决这个问题。
sim++:(保证操作正确性)
TestAndSet(&lock),等价exchange
中断
软件处理
* 实现条件同步:线程A在线程B后执行
信号量初始值:0
信号量解决生产者,消费者问题
emptyBuffers->P()
mutex->P(); 两者交换,程序出现死锁

mutex-V()
fullBuffers->V()两者交换顺序,对程序正确性没有任何影响。

第二种同步方法:管程
信号量:P,V 操作分配在生产者与消费者中,P,V的配对是比较困难的。
信号量使用锁,管程使用条件变量,在解决同步互斥问题上,信号量与管程等价。
管程:P,V操作的配对,集中在一起
(1)管程采用面向对象的方法,简化了线程间的同步控制。
(2)任何时刻只有一个线程在执行管程代码
(3)临界区也是任何时刻只有一个线程在执行管程代码,但是他们有区别,区别是:正在管程中的线程可临时放弃管程的互斥访问,等待事件出现时恢复。

管程的使用:
在对象、模块中收集相关共享的数据
定义访问共享数据的方法,在其他地方不需要同步互斥操作了。
管程也可能出现死锁的情况
管程中的局部变量不可以被外部直接访问
管成组成:
一个锁(入口,出口)
控制管程代码的互斥访问
0或者多个条件变量
管理共享数据的并发访问
临界区只有一个条件变量,而管程管理一系列的条件变量

条件变量
条件变量是管程内的等待机制
进入管程的线程因资源被占用而进入等待状态
每个条件变量表示一种等待原因,对应一个等待队列
Wait()操作
将自己阻塞在等待队列中
唤醒一个等待者或释放管程的互斥访问
与信号量区别:不用判断sim/numWaiting是否为空,直接加入waitQueue 中,而且不用管配对的问题。
Signal()操作
将等待队列中的一个线程唤醒
如果等待队列为空,则等同空操作
用管程解决生产者-消费者问题
效率不如信号量的效率

读者、写者问题:
规则:“读-读“允许 “写-读”互斥” ‘ “写-写”互斥

管程实现读者-写者问题
AR=0 Active readers 当前正在读的读者
AW=0 当前正在写的写者
WR=0 当前等待的读者
WW=0 当前等待的写者

读者-写者问题 (考试实现读者优先),
读者优先
写者端: StrarWrite() while(while(AR+WR>0)){okToWrite.wait()}
DoneWrite() if(AW==0&&WR>0){okToRead.signal()}

读者端:
StartRead() while(AW+AR>0){okToRead.wait()}
DoneRead() if(WR>0){okToRead.signal()}else if(WW>0){okToWrite.signal()}

写者优先
读者端:
stratRead()函数:while(AW+WW>0){ okToReda.wait()}
DoneRead()函数: if(AR==0&&WW>0) //没有读者且有写者等着则释放锁
oktowrite.signal()

写者端:
startWrite() while((AW+AR)>0){ okToWrite.wait} 但是有等待读的读者,是不等的,则说明是写者优先的
DoneWrite if(WW>0){okToWrite.signal()}else if(WR>0){okToRead.broadcast()}

这篇关于操作系统的信号量和管程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/870166

相关文章

高效管理你的Linux系统: Debian操作系统常用命令指南

《高效管理你的Linux系统:Debian操作系统常用命令指南》在Debian操作系统中,了解和掌握常用命令对于提高工作效率和系统管理至关重要,本文将详细介绍Debian的常用命令,帮助读者更好地使... Debian是一个流行的linux发行版,它以其稳定性、强大的软件包管理和丰富的社区资源而闻名。在使用

龙蜥操作系统Anolis OS-23.x安装配置图解教程(保姆级)

《龙蜥操作系统AnolisOS-23.x安装配置图解教程(保姆级)》:本文主要介绍了安装和配置AnolisOS23.2系统,包括分区、软件选择、设置root密码、网络配置、主机名设置和禁用SELinux的步骤,详细内容请阅读本文,希望能对你有所帮助... ‌AnolisOS‌是由阿里云推出的开源操作系统,旨

五大特性引领创新! 深度操作系统 deepin 25 Preview预览版发布

《五大特性引领创新!深度操作系统deepin25Preview预览版发布》今日,深度操作系统正式推出deepin25Preview版本,该版本集成了五大核心特性:磐石系统、全新DDE、Tr... 深度操作系统今日发布了 deepin 25 Preview,新版本囊括五大特性:磐石系统、全新 DDE、Tree

Linux操作系统 初识

在认识操作系统之前,我们首先来了解一下计算机的发展: 计算机的发展 世界上第一台计算机名叫埃尼阿克,诞生在1945年2月14日,用于军事用途。 后来因为计算机的优势和潜力巨大,计算机开始飞速发展,并产生了一个当时一直有效的定律:摩尔定律--当价格不变时,集成电路上可容纳的元器件的数目,约每隔18-24个月便会增加一倍,性能也将提升一倍。 那么相应的,计算机就会变得越来越快,越来越小型化。

1、简述linux操作系统启动流程

1、简述linux操作系统启动流程 启动第一步--加载BIOS 当你打开计算机电源,计算机会首先加载BIOS信息,BIOS信息是如此的重要,以至于计算机必须在最开始就找到它。这是因为BIOS中包含了CPU的相关信息、设备启动顺序信息、硬盘信息、内存信息、时钟信息、PnP特性等等。开机时将ROM中的指令映射到RAM的低地址空间,CPU读取到这些指令,硬件的健康状况进行检查,按照BIOS中设置的启

操作系统是怎么为不同的程序分配所需的内存空间的

操作系统为不同的程序分配内存空间的过程涉及多个关键步骤,确保每个程序都有其所需的内存资源,同时避免程序之间的冲突。以下是操作系统如何为程序分配内存空间的详细过程: 1. 内存管理的基础概念 虚拟内存:现代操作系统使用虚拟内存机制来为程序提供隔离的内存空间。每个程序运行在其独立的虚拟地址空间中,这使得程序间的内存互不干扰。物理内存:实际的 RAM(随机存取存储器),由操作系统和硬件共同管理。虚拟

操作系统安全保护

操作系统安全概述 概念:满足安全策略要求,具有响应安全机制及安全功符合特定安全标准,在一定约束条件下 能抵御常见网络安全威胁,保障自身安全运行及资源安全 安全等级:根据安全功能和安全保障要求分为 用户自主保护级  系统审计保护级 安全标记保护级 结构化保护级 访问验证保护级 操作系统作用: 负责计算系统的资源管理、支撑和控制各种应用程序运行,为用户提供计算机系统管理接口 是构成网络信息

Linux操作系统命令集(一)

最近开了操作系统的课,弄着虚拟机的linux系统命令学学 文件和目录操作命令: ls:列出目录内容 示例:ls -l 以长格式列出目录内容cd:切换目录 示例:cd /home/user 切换到 /home/user 目录mkdir:创建目录 示例:mkdir new_directory 创建名为 new_directory 的目录rmdir:删除空目录touch:创建空文件或更新文件的时间戳

Linux多线程——POSIX信号量与环形队列版本之生产消费模型

文章目录 POSIX信号量POSIX的操作初始化销毁等待信号量(申请资源)发布信号量(放下资源) 环形队列之生产消费模型 POSIX信号量 POSIX信号量和System V信号量是不同的标准 但是实现的功能是一样的,都是为了解决同步的问题 我们说信号量指的就是资源的数量 在生产者与消费者模型里面,生产者与消费者所认为的资源是不同的 生产者认为空间是资源,因为每次都要

操作系统分页式存储管理

每次输入地址后,计算出页号,若页号越界,则给出错误提示。否则依次调用FIFO和LRU算法,这里值得注意的是,由于我们的FIFO算法先于LRU算法被调用,那么当在处理FIFO算法时,我们暂且不将位视图相应位置做变化,留到处理LRU算法再做处理。 对于FIFO、LRU算法的缺页,我们分两种情况考虑,第一种是模拟栈内还有空间,那么直接将其入栈。第二种是模拟栈内无空间,要发生置换。发生置换时把模拟栈最底