如果同一时刻系统某一资源,被两个进程并发地访问,可能会达不到原本的目的,甚至打乱了原有的工作,比如说进程a,b共享打印机资源,同时向外输出,这样a输出一段,b输出一段,就会使a,b的内容糅杂在一起。这样,就必须使进程互斥着访问,同一时刻只能有一个进程单独访问,该被访问的资源,被称为临界区。
另外,进程互斥要遵循以下规则。
1.空闲让进,临界区空闲时,应允许一个进程访问
2.忙则等待,临界区正在被访问时,其他试图访问的进程需要等待
3.有限等待,要在有限时间内进入临界区,保证不会饥饿
4.让权等待,进不了临界区的进程,要释放处理机,防止忙等
为了实现以上进程互斥的想法,提供了软件和硬件的实现方式。
1.软件实现方式
1.单标志法
int turn = 0; //turn 表示当前允许进入临界区的进程号
turn 的初值为0,即刚开始只允许0号进程进入临界区。
若P1先上处理机运行,则会一直卡在。直到 P1 的时间片用完,发生调度,切换 P0上处理机运行
代码不会卡住 P0,P0可以正常访问临界区,在 P0 访问临界区期间即时切换回 P1,P1依然会卡在while。只有P0在退出区将 turn 改为1后,P1才能进入临界区。
因此,该算法可以实现“同一时刻最多只允许一个进程访问临界区。
缺点不遵循空闲让进原则。
2.双标记先检查
在单标记法上将turn改为了一个flag数组。
若按照152637顺序执行,P0和 P1将会同时访问临界区,因此,双标志先检查法的主要问题是:违反“忙则等待”原则。原因在于,进入区的“检查”和“上锁”两个处不是一气呵成的。“检”后,“上锁”前可能发生进程切换。
3.双标志后检查
若按照1526的顺序执行,P0和 P1将都无法进入临界区,因此,双标志后检查法虽然解决了“忙则等待”的问题,但是又违背了“空闲让进”和“有限等待”原则,会因各进程都长期无法访问临界资源而产生“饥饿”现象。
4.Peterson算法
Peterson算法用软件方法解决了进程互斥问题,遵循了空闲让进、忙则等待、有限等待 三个原则,但是依然未遵循让权等待的原则。
2.硬件实现
1.中断屏蔽
利用“关/开中断”实现。
关中断后即不允许当前进程被中断,也必然不会发生进程切换直到当前进程访问完临界区,再执行开中断指令,才有可能有别的进程上处理机并访问临界区
优点:简单、高效
缺点:不适用于多处理机:只适用于操作系统内核进程,不适用于用户进程(因为开/关中断指令
只能运行在内核态,这组指令如果能让用户随意使用会很危险)
2.tsl
若刚开始 lock 是 false,则TSL 返回的old 值为 false,while 循环条件不满足,直接跳过循环,进入临界区。若刚开始 lock是 true,则执行TLS 后ld 返回的值为 true,while 循环条件满足,会一直循环,直到当前访问临界区的进程在退出区进行“解锁”相比软件实现方法,TSL 指令把“上锁”和“检查”操作用硬件的方式变成了一气呵成的原子操作。
优点:实现简单,无需像软件实现方法那样严格检查是否会有逻辑漏洞;适用于多处理机环境
缺点:不满足让权等待