前言
当进程运行时,对于各种资源的访问非常频繁,因此掌握进程同步和进程互斥极为关键,下面让我带领大家逐一突破它们。
进程同步
引入进程同步之前,先举一个编写Java程序的小例子:
int result=10;//定义并赋值
System.out.println(result);//输出
上面的代码,“定义并赋值”操作必须在“输出”操作之前,不然程序将会报错,若把两种操作看作两个进程,那么这就是进程同步。
什么是进程同步?
定义:在多道程序环境下,进程是并发执行的,不同进程之间存在着不同的相互制约关系。
进程互斥
引入进程互斥之前,先举一个生活中的小例子:
若校园内的只有一辆环校车,并且有多个位置,司机需要一个位置,还有多个位置供同学乘坐,刚好有两位同学需要乘坐环校车,那么两个同学可以同时这趟环校车,即这方式便是同时共享同一资源。
若校园内的只有一辆环校车,并且只有两个位置,司机需要一个位置,只有一个位置供同学乘坐,刚好有两位同学需要乘坐环校车,那么必有一个同学需要等待环校车的下一趟,即这方式便是互斥共享同一资源,进程互斥的原理与这个例子类似。
什么是进程互斥?
定义:在多道程序环境下,对临界资源的访问,需要互斥的进行,即同一时间段内只能允许一个进程访问该资源。
操作系统中,进程互斥由四个部分构成:
进入区:检查是否可进入临界区,若可进入,需要“上锁”。
临界区:访问临界资源的那段代码。
退出区:负责“解锁”。
剩余区:其余代码部分。
do{
entry section; //进入区
critical section; //临界区
exit section; //退出区
remainder section; //剩余区
}while(true)
解释:进入区和退出区实现进程互斥的必要操作,进程进入之前,需要“上锁”,不允许它在访问资源时,其余进程也进来访问,进程退出之后,需要“解锁”,该进程用完后,需要打开权限供下一个用户使用,因此这两个区域存在是非常必要的。
临界区即是进程访问核心区,进程在这里可以访问到它需要的资源。
那么大家可能会疑惑,为什么还要定义个剩余区呢?
其实,这个区域的代码与进程无关,若全部逻辑代码都放在临界区,该代码必将冗余,不符合编程代码规范,便多定义个剩余区。
操作系统中,进程互斥需要遵循以下规则:
- 空闲让进:临界区空闲时,可以允许一个请求进入临界区的进程立即进入临界区;
- 忙则等待:当已有进程进入临界区时,其他试图进入临界区的进程必须等待;
- 有限等待:对请求等待的进程,应保证在有限时间内能够进入临界区(保证不会出现饥饿现象);
- 让权等待:当进程不能进入临界区时,应立即释放处理机,防止进程忙等待。
解释:其实进程互斥的需要遵循的规则,是对进程互斥定义的详细描述。
信号量机制
实现进程互斥的方法:
软件实现:
硬件实现:
以上多种实现进程互斥的方法,只是简单给出了定义,如果大家要进一步研究,则需要在网上查找其相关资料进行学习;上面那么多种都有一些问题,为了解决该问题,荷兰学者Dijkstra提出了一种卓有成效的实现进程互斥的方法,即信号量机制,并且该方式来可实现进程同步操作。
信号量机制可分为整型信号量和记录型信号量:
整型信号量:
记录型信号量:
记录型信号量的解释:
小总结:
用信号量实现进程同步、互斥和前驱关系
下面是用信号量实现进程同步:
下图是用信号量实现进程互斥:
下图是实现信号量实现进程的前驱关系:
小总结:
总结
从上面学习中,大家不难发现,进程的互斥和同步这两种操作在生活中无处不在,对于进程互斥的遵守规则,我认为可以适当运用于生活中,这也可以达到学以致用的目的,同时也可以让我们生活变得更好!
该文章的编写参考王道考研的操作系统课程。
文中若内容出现不足之处,望读者在评论区踊跃发表观点!