【操作系统】第六章 进程同步

6.1 背景
1)竞争条件:多个进程并发访问和操作同一数据且执行结果与访问发生的特定顺序有关。

6.2 临界区问题
1)临界区:在该区中进程可能改变共享变量、更新一个表、写一个文件等;
2)引入临界区之后典型进程Pi通用结构如图;
【操作系统】第六章 进程同步_第1张图片
3)临界区特征:当一个进程进入临界区,没有其他进程可被允许在临界区内执行;
4)临界区问题:设计一个以便进程协作的协议;
5)临界区问题满足要求:
a)互斥;
b)前进;
c)有限等待;
6)操作系统临界区问题解决:
a)抢占内核(有竞争条件);
b)非抢占内核(无竞争条件);

6.3 Peterson算法
1)思想:进程想进入临界区,先表明一下意向(flag[i]=true),然后很客气的让其他想进入临界区的进程先进入(turn=j),以解决临界区问题,算法表示如下图(操作系统书第169页):
【操作系统】第六章 进程同步_第2张图片
2)证明满足临界区问题:
a)互斥:当只有flag[j]==false || turn==i时,进程Pi才进入其临界区。而且,注意到如果两个进程都在其临界区内执行,有flag[0]==flag[1]==true。这就意味着P0和P1不可能成功地同时执行它们的while语句,因为turn的值只能为0或者1。因此,只有一个进程(假设为Pj)能成功执行完while语句,而进程Pi至少必须执行一个附加的语句(turn==j),并且,由于只要Pj在其临界区内,flag[j]==turn && turn==j就成立,因此互斥成立;
b)前进以及有限等待:只要flag[j]==trun和turn==j成立,进程Pi陷入while循环语句,那么Pi被阻止进入临界区。如果Pj不准备进入临界区,那么flag[j]==false,Pi能进入临界区。如果Pj设置了flag[j]==true并且在while语句中执行,那么turn的值决定了哪一个进程进入临界区。如果turn==i,那么Pi进入临界区,如果turn==j,那么Pj进入临界区。当Pj退出临界区时,flag=[j]会设置为false,以允许Pi进入其临界区。如果flag[j]被重新设置为true,那么turn也被设置为i,因此由于进程Pi执行while语句时并不改变turn的值,所以Pi进入临界区,满足前进,且Pi最多在Pj进入其临界区一次后就能进入临界区,满足有限等待。

6.4 硬件同步
1)TestAndSet()指令和Swap()指令,如下图(操作系统书第171页):
【操作系统】第六章 进程同步_第3张图片
2)用TestAndSet实现有限等待互斥,代码中所有数据结构均初始化为false(操作系统书第171页):
【操作系统】第六章 进程同步_第4张图片

6.5 信号量
1)信号量除了初始化之外,只能通过两个标准的原子操作:wait()和signal()来访问(PV操作);
2)用法:如图(操作系统书第173页)
【操作系统】第六章 进程同步_第5张图片
3)实现:取消应用程序进入临界区的忙等
【操作系统】第六章 进程同步_第6张图片
【操作系统】第六章 进程同步_第7张图片

6.6 经典同步问题
1)有限缓冲问题:提供一个有限缓冲供消费者拿取和生产者填充;
2)读者-写者问题:
a)无写者在CS时读者都无需等待——写者饥饿;
b)有写者在CS时读者需等待——读者饥饿;
3)哲学家进餐问题;

6.7 管程
1)管程类型:提供了一组有程序员定义的、在管程内互斥的操作;

6.8 同步实例
1)Solaris同步:
a)适应互斥:如果锁是被正在另一个CPU上运行的线程所拥有,那么拥有锁的线程可能会很快结束,所以请求锁的线程就自旋并等待锁可用。如果拥有锁的线程现在不处于运行状态,那么线程就阻塞进入睡眠,直到锁释放时被唤醒;
b)十字转门:一个队列结构,包含阻塞在锁上的线程;
2)Windows XP同步:
a)保护拥有自旋锁的线程决不会被抢占;
b)触发状态通过线程获取互斥锁进入非触发状态,非触发状态通过线程释放互斥锁进入触发状态;
3)Linux同步:
a)单核处理器的禁止内核抢占——多核处理器的获取自旋锁;
b)单核处理器的使用内核抢占——多核处理器的释放自旋锁;
4)Pthread同步;

6.9 原子事务
1)事务:执行单个逻辑功能的一组指令或操作,要么与其相关的所有操作都执行完,要么什么操作都不做;
2)确保原子性的方法:
a)基于日志的恢复:
i 日志存储内容:事务名称、数据项名称、旧值、新值;
ii 恢复:如果日志包含记录但没有包含记录,撤销:undo (Ti);
如果日志包含记录和记录,事务重做:redo(Ti);
b)检查点:
i 工作:首先向后搜索日志查找到第一条记录,则只需要对其后执行恢复;
ii 恢复:如果日志包含记录但没有包含记录,撤销:undo (Ti);
如果日志包含记录和记录,事务重做:redo(Ti);
3)并发原子操作确保串行化:加锁协议(增长阶段、收缩结点)和时间戳顺序协议。

你可能感兴趣的:(操作系统)