操作系统入门 – 进程的同步与互斥
在之前的文章中,我们了解了进程是如何被调度的。但在调度之前,进程需要获得资源。而获得这些资源则可能让进程之间陷入冲突。为了高效且平等地调度线程,需要引入同步功能。
1.临界资源
1.1 临界资源的描述
在操作系统中进程占用的最小资源(线程仅访问所在进程的资源,因此线程并不占资源)。但某些资源在同一时刻只能被一个进程占用,类似这样的进程为临界资源。例如打印机、存在内存或硬盘中被多个进程共享的一些变量或数据等。
1.2 临界资源的性质
对临界资源访问的方式为互斥,即当一个进程持有该资源时,其他进程无法访问,只有当该持有资源的进程释放后才能被其他进程访问。其访问方式如下
- 进入区:查看临界区是否可以访问,若可以则进行下一步,否则为阻塞。
- 临界区:在临界区操作。
- 退出区:清除临界区被占用的标志。
- 剩余区:进程与临界区不相关部分的代码。
2.同步与互斥
2.1进程同步
进程同步是进程之间的制约关系,其目的是为了完成某个任务而建立的两个或多个线程。这些线程将会在某些位置上协调进程之间的工作次序、传递信息。
- 例子:如图所示,进程B需要在缓冲区读取到进程A产生的信息才能执行,否则将处于阻塞状态。
2.2进程互斥
同理,互斥也是进程间的一种制约关系。当存在两个进程需要请求临界资源时,得到临界资源的进程将开始执行,另一个为得到临界资源的进程进入阻塞。只有当前一个进程释放资源后,后一个进程才能解除阻塞。
- 例子:如图所示,A、B两个进程都要请求打印机资源,此时A先获得打印机资源,因此A执行,B阻塞。当A执行完毕后再执行B
3.实现临界区互斥的基本方法
3.1 软件方法
Dekker算法和peterson算法
3.2 硬件方法
通过硬件实现临界区的办法就是使用CPU中断。CPU进程切换是通过中断实现的,当把中断屏蔽后,当前进程就可以顺利将临界区代码执行完毕,从而实现互斥。具体步骤为:屏蔽中断->执行临界区->开中断。但这样运行的缺点是大大限制了处理器交替执行任务的能力。接下来将讲解另一种实现方法。
3.3 信号量实现
在上述硬件实现临界区互斥的方法可以了解到效率并不高,因此可以设置一个表示资源个数的信号量S,通过S的P(占有)和V(释放)操作实现。其中P、V操作为系统原语,意味着这两个操作为原子操作(原子操作指的是由多步操作组成的一个操作。如果该操作不能原子地执行,则要么执行完所有步骤,要么一步也不执行,不可能只执行所有步骤的一个子集)。
P操作首先减少信号量,表示有一个进程将占用或等待资源,之后检查S是否小于0,若小于0则阻塞,大于0则占有资源执行。
V操作与P操作相反,首先增加信号量,表示占用或等待资源的进程减少了1个,然后检测S是否小于0,如果小于0则唤醒等待使用S资源的其它进程。
4.利用信号量实现同步的经典问题
4.1 生产者-消费者问题
在该作业中,要求设计在同一个进程地址空间内执行的两个线程。生产者线程生产物品,并放置在一个空的缓冲区供消费者线程使用。消费者线程从缓冲区中获得物品,并释放缓冲区。当缓冲区再无可用空间时,生产者线程会开始等待,当消费者线程释放缓冲区后,生产者线程才会继续生产。当缓冲区为空时,消费者线程也会进入阻塞状态,直到生产者线程产生物品。
这里生产者和消费者是既同步又互斥的关系,首先只有生产者生产了,消费着才能消费,这里是同步的关系。但他们对于临界区的访问又是互斥的关系。
4.2 读者-写者问题
问题描述:一个数据文件或记录,统称数据对象,可被多个进程共享,其中有些进程只要求读称为”读者”,而另一些进程要求写或修改称为”写者”。
规定:允许多个读者同时读一个共享对象,但禁止读者、写者同时访问一个共享对象,也禁止多个写者访问一个共享对象,否则将违反Bernstein并发执行条件。
从上述题目中可以了解到,读者和写者是互斥的,不同写者之间也是互斥的。因此我们可以设置3个变量,一个用来统计读者的数量,另外两个分别用于对读者数量读写的互斥,读者和读者写者和写者的互斥。