操作系统概念学习笔记 第七章 进程同步
协作进程是可以与在系统内执行的其他进程互相影响的进程。可以直接共享逻辑地址空间(包括代码和数据),或者只通过文件共享数据。
临界区域问题:
考虑一个系统有n个进程,每个进程有一个代码段称为临界区,在该区中进程可能改变共同变量、更新一个表、写一个文件等。
这种系统的重要特征是当一个进程在临界区内执行,没有其他进程被允许在临界区内执行。
进程临界区在执行的时间上互斥。临界区问题是设计一个进程能用来协作的协议。每个进程必须请求允许进入其临界区。
实现这一请求的代码段称为进入区。临界区之后可有退出区。其他代码为剩余区。
临界区问题的解答必须满足三项要求:
1 互斥:只能一个进程在临界区内执行
2 有空让进:如果没有进程在其临界区内执行且有进程希望进入临界区,那么只有那些不在剩余区内执行的进程能参加决策,以选择谁能下一个进入临界区,且这种选择不能无限推迟。
3 有限等待:在一个进程作出进入其临界区的请求到该请求被允许期间,其他进程被允许进入其临界区的次数存在一个上限
两进程解法:
进程共享两个变量:bool数组 flag[2],int turn;
为了进入临界区,进程p首先设置flag[i]的值为true,且设置turn的值为j
多进程解法:
面包店算法:进入商店,每个客户接收一个号码,具有最小号码的客户先得到服务,出现相同号码时,具有最小名称的进程先得到服务。
同步硬件:
硬件特征能简化编程任务且提高系统效率。
信号量:
互斥解决方案和这里定义的信号量的主要缺点是都要求求忙等待。
当一个进程位于其临界区内时,任何其他视图进入其临界区的进程都必须在其进入代码中连续地循环。浪费CPU时钟。
这种类型的信号量也称为自旋锁(因为进程在等待锁时“自旋”)。
自旋锁的优点是在进程必须等待一个锁时无需上下文切换。
死锁与饥饿
死锁:组内的每个进程都等待一个事件,而该事件可只能由组内的另一个进程产生。
饥饿(无期限阻塞):进程在信号量内无穷等待的情况
经典同步问题:
管程:
是由程序员定义的一组操作符来表征的。
管程类型的表示包括一组变量的声明(这些变量的值定义了一个类型实例的状态)和实现对这些类型操作的子程序体和函数体。
管程类型的表示不能直接为各个进程所使用,在管程内定义的子程序只能访问位于管程内那些局部声明的变量和其形式参数。类似的,管程的局部变量只能为局部子程序所访问。
管程构造确保一次只有一个进程能在管程内活动。
操作系统同步:
原子事务:
数据库关注于数据的存储和提取以及数据的一致性。近来,有一个将数据库系统技术应用于操作系统的热潮。操作系统可看做数据的操作者,这样,也能得益于数据库研究所得的高级技术和模型。
系统模型:
执行单个逻辑功能的一组指令(或操作)称为事务。处理事务的主要问题是不管计算机系统出现什么可能的失败,都要保证事务的原子性。事务是访问且可能更新各种驻留在磁盘文件中的数据项的程序单元。
各种数据设备的属性:
1 易失性存储:访问快,系统崩溃后不能保存
2 非易失性存储:系统崩溃后能保存,访问慢
3 稳定存储:需要在多个非易失性存储介质上以独立失败模式复制信息,并按一定的控制方式来更新信息。
基于日志的恢复:
在稳定存储上记录有关事务对其访问的各种数据所做各种修改的描述信息。最为常用方式是先记日志后操作。系统在稳定存储上维护一个称为日志的数据结构。
每个日志记录描述了一个事务写出的单个操作,并具有如下域:
1 事务名称:执行写操作事务的唯一名称
2 数据项名称:所写数据项的唯一名称
3 旧值:写操作前的数据项的值
4 新值:写操作后的数据项的值
其他特别日志记录用于记录事务处理的重要事件,如事务开始和事务的提交或放弃。
因为日志信息用于构造各种事务所访问数据项的状态,所以在相应日志记录写出到稳定存储之前不能允许真正地更新数据项。
缺点:
1 搜索进程费时
2 恢复需要较长时间
检查点:
为了降低只通过日志恢复数据的额外开销。引入检查点概念。系统定期执行检查点并需要执行如下动作:
1 将当前驻留在易失性存储上的所有日志记录输出到稳定存储上
2 将驻留在易失性存储上的所有修改数据输出到稳定存储上
3 在稳定存储上输出一个日志记录
并发原子事务:
因为每个事务是原子性的,所以事务的并发执行必须相当于这些事务按某任意顺序串行执行,这一属性,称为串行化。
1 串行化能力
2 加锁协议
1 共享:共享模式锁,可以读,不能写
2 排他:排它模式锁,可读可写
两阶段加锁协议:
1 增长阶段:事务可获取锁,但不能释放任何锁
2 收缩阶段:事务可释放锁,但不能获取任何新锁
3 基于时间戳的协议
确定串行化顺序的另一个方法是事先在事务之间选择一个顺序,这样做的最为常用方法是使用时间戳排序方案。
对于系统内的每个事务,都为其关联一个唯一固定时间戳,并记为TS,在事务开始执行前,由系统赋予。
以后进入系统的新事务时间戳大于以前的事务的时间戳。
有两种简单的方法实现:
1 采用系统时钟值作为时间戳,即事务时间戳等于当事务进入系统时的时钟值。这种方法不适用于处于不同系统上的事务,也不适用于不共享时钟的多处理器系统。
2 采用逻辑记数器作为时间戳,即事务时间戳等于当事务进入系统时的计数器的值,在赋予了新时间戳后,计数器的值增加。
为每个数据项Q关联两个时间戳的值:
1 W-timestamp(Q):表示任何事务成功执行write(Q)的最大时间戳
2 R-timestamp(Q):表示任何事务成功执行read(Q)的最大时间戳
只要执行指令write(Q)和read(Q)时,就更新这些时间戳。
时间戳顺序协议确保任何冲突操作read和write按时间戳顺序执行。工作如下:
*假定事务发出read(Q):
如果TS<W-timestamp(Q),那么这个状态表示事务需要读Q的值,但是其值被改写,因此操作read拒绝,
如果TS>=W-timestamp(Q),那么就执行操作read,R-timestamp(Q)就设置成R-timestamp(Q)和TS的最大值
*假定事务发出write(Q):
如果TS<R-timestamp(Q),表示数据项正在被读,不能执行写操作
如果TS<W-timestamp(Q),表示事务试图写的数据已过时,不能执行写操作
否则执行写操作
由于发出操作而被并发控制算法返回的事务,被赋予新时间戳并重新开始。

浙公网安备 33010602011771号