思维导图:
什么是互斥?
实例:
互斥共享方式:打印机。一次只允许一个文件被打印
同时共享方式:看小说的软件,多人在线同时读
!!程序并非一直都在访问共享空间!!
程序一般被分为四个区域:
进入区:这一部分书写的是进入临界区(获取资源)的代码
退出区:这一部分书写的是退出临界区(让出资源)的代码
临界区:书写着要对临界区的读写操作
剩余区:一些程序代码。
什么是同步?
互斥模块:
part 1:软件实现方式(单标志、双标志先检查、双标志后检查、Peterson)
单标志法:
核心思想:通过确定turn的值来确定自己是否有访问的权限
缺陷:因为turn的值只会在其他进程运行的时候改变。不符合“空闲让进”
双标志法先检查法:
核心:每个进程之间去检查其他的进程是否进入程序,如果没进自己进
缺陷:不满足“忙则等待”,因为异步性,两个while有可能一起结束,都执行flag代码,那就两个都进入了区域内。
双标志后检查法:
算法核心与前面的相反,会自己先改变变量然后才去确定其他进程是否在访问。
缺陷,存在多个进程都设置了希望进入进程的变量。但卡在循环这里,造成死循环。
Peterson 算法(谦让精神)
让在何处?
核心是在TA会先表示“自己想进去的意愿”,然后去设置进入共享资源的变量,表示对方可以先进去
ps:最先发出想进入(即:flag=true)的先进
part2:进程互斥的硬件实现方法(中断屏蔽、TestAndSet 指令、Swap 指令)
核心:开/关中断的应用
TestAndSet 指令
算法核心:1、通过输入lock=true值表示希望访问临界资源。2、通过返回值确定是否可以进入。false为可进入,true为此共享资源正在被访问,3、注意:其他进程访问访问完要把进程改为false,让其他进程进入
Swap 指令(XCHG 指令)
算法核心:1、通过输入old=true值表示希望访问临界资源。2、进程中lock表示锁,通过函数调换lock和old的值,在无进程访问的时候交换结果的值,old=false,同时lock的值被设置为true,3、注意:其他进程访问访问完要把进程改为false,让其他进程进入
part3:信号量机制(整形信号量、记录型信号量)
同步和互斥多使用信号量机制。
整形变量没有脱离忙则等待的问题
问题场景描述:在计算机运行中存在一个进程要很多共享资源,有可能出现a进程拿了一半,b进程拿了另一半,他们刚好缺对方的一般而造成死循环。
故有了这一设计,体现让权等待的“让”的思想
核心:信号量为正表示可用资源,为负表示在等待的资源,PV操作分别代表申请和归还资源。
ps:下面实例都是通过记录型变量实现的
用信号量机制实现进程互斥、同步、前驱关系
信号量机制实现进程互斥
通过调用互斥信号量,实现进入、退出共享资源(pv一定要成对出现)
信号量机制实现进程同步
核心点:后执行在开头先p,先执行的在末尾加v
信号量在解决前驱(同步)问题的应用
信号量的应用
- 单生产者对单消费者
- 多生产者对多消费者
- 单生产者对多消费者
- 读者写者问题
- 哲学家进餐问题
单生产者对单消费者(相对简单)
问题描述
核心点/注意点:当生产者能放入的资源满了,不能继续生产,当缓冲区为空不能进行取东西操作。
多生产者对多消费者
问题描述:
核心点:共享资源的数量是固定的,一个生产者对应一个消费者,多个生产者去生产东西都放在同一个缓冲区内,差别在于你要让谁拿东西,
故可得一个关系:生产者对缓存空间p操作,然后一对生产者和消费者关系,需要另外定义一个变量让生产者唤醒对应的消费者,
消费者则需要在消费完后,释放被占用的内存内存空间
即:
单生产者多消费者
问题描述:
算法核心:生产者生产对应的东西,就去拍一拍对应的生产者来拿东西
由此可得关系,在代码设计时x个消费者对应x个信号量 生产者生产完会占用一个缓冲空间(p操作)然后让对应的消费者来拿V(i)i in x。
代码实现:
读者-写者问题:
问题描述:
代码实现:
这里其实有一个容易产生误区的点:这里有多个读者,这一段是一个伪代码,实际运行中是有上百甚至上千的人在执行这个代码,这会创建上千个一样的进程,跑一样的代码
描述代码:写者就是正常的上锁、写东西、解锁 读者则是第一个读的人要负责上锁,最后一个读的人要负责解锁。潜在问题:如果有人在读就一直不解锁
现实中,作者一般就上传内容时间短,且读者需要作者更新读者才能看新的东西,故作者优先级应该高于读者。
改进:
哲学家进餐问题
问题描述:
解决方法:
这个涉及到死锁的避免,可以在死锁那一篇具体讨论