目录
一、进程同步的基本概念
1.1互斥与同步
进程同步的概念 —— 协作进程间的制约关系
1.主要任务:使并发执行的诸进程之间能有效地共享资源和相互合作,从而使程序的执行具有可再现性。
2.进程间的制约关系
(1)间接相互制约关系(互斥关系) :进程互斥使用临界资源。
(2)直接相互制约关系(同步关系):进程间相互合作。
3.临界资源
系统中某些资源一次只允许一个进程使用,称这样的资源为临界资源或互斥资源或共享变量。
诸进程间应采取互斥方式,实现对这种资源的共享。
数据不一致例子:生产者-消费者问题:
共享变量:
缓冲池buffer: 用数组来表示具有n个缓冲区的缓冲池。
输入指针in: 指示下一个可投放产品的缓冲区,每当生产者进程生产并投放一个产品后,输入指针加1,初值为0。
输出指针out: 指示下一个可获取产品的缓冲区,每当消费者进程取走一个产品后,输出指针加1,初值为0。
整型变量count: 初值为0,表示缓冲区中的产品个数。
生产者进程: producer():
消费者进程:consumer ():
count++和count--的机器语言:
1.2临界区问题
① 进入区(entry section):用于检查是否可以进入临界区的代码段。
② 临界区(critical section) :进程中涉及临界资源的代码段
③ 退出区(exit section) :将临界区正被访问的标志恢复为未被访问标志。
④ 剩余区:其他代码
同步机制应遵循的准则:
进程同步机制:
(1)软件同步机制:使用编程方法解决临界区问题 ; 有难度、具有局限性,现在很少采用
(2)硬件同步机制:使用特殊的硬件指令,可有效实现进程互斥
(3)信号量机制:一种有效的进程同步机制,已被广泛应用
(4)管程机制:新的进程同步机制
知识回顾
二、进程同步机制
2.1软件同步机制
Peterson解决方案:适用于两个进程交替执行临界区
示例:
2.2硬件同步机制
1. 关中断:(进关,完开)
进入锁测试之前关闭中断,完成锁测试并上锁之后才打开中断
可有效保证互斥,但存在许多缺点
2. Test-and-Set指令
Test-and-Set指令实现互斥:
3. Swap指令
缺点:不符合“让权等待”原则,浪费CPU时间;很难解决复杂的同步问题。
swap指令实现互斥:
2.3信号量机制
1965年,由荷兰学者迪科斯彻Dijkstra提出(P、V分别代表荷兰语的Proberen (test)和Verhogen (increment)),是一种卓有成效的进程同步机制。
信号量-软件解决方案:
保证两个或多个代码段不被并发调用。
在进入关键代码段前,进程必须获取一个信号量,否则不能运行。
执行完该关键代码段,必须释放信号量。
信号量有值,为正说明它空闲,为负说明其忙碌。
类型:整型信号量、记录型信号量、AND型信号量、信号量集
2.3.1信号量的类型
2.3.1.1整型信号量
2.3.1.2记录型信号量:去除忙等的信号量
每个信号量S除一个整数值S.value外,还有一个进程等待队列S.list,存放阻塞在该信号量的各个进程PCB.
信号量只能通过初始化和两个标准的原语PV来访问--作为OS核心代码执行,不受进程调度的打断。
初始化指定一个非负整数值,表示空闲资源总数(又称为"资源信号量")--若为非负值表示当前的空闲资源数,若为负值其绝对值表示当前等待临界区的进程数。
wait、signal操作定义:
记录型信号量实现资源申请、释放:
2.3.1.3 AND型信号量
AND型信号量同步的基本思想:将进程在整个运行过程中需要的所有资源,一次性全部分配给进程,待进程使用完后再一起释放。
对若干个临界资源的分配,采用原子操作。
在wait(S)操作中增加了一个“AND”条件,故称之为AND同步,或同时wait(S)操作,即Swait(Simultaneous wait)。
AND型信号量操作定义:
2.3.1.4信号量集
在记录型信号量中,wait或signal仅能对某类临界资源进行一个单位的申请和释放,当需要对N个单位进行操作时,需要N次wait/signal操作,效率低下。
2.3.2信号量的应用
2.3.2.1利用信号量实现进程互斥(互斥信号量)
2.3.2.2利用信号量实现进程同步(同步信号量)
实现各种同步问题——进程同步:让各并发进程按要求有序推进
例子:P1和 P2 需要代码段 C1 比C2先运行
semaphores s=0; //主要用于传递消息
2.3.2.3利用信号量实现前趋关系
知识回顾
2.4管程机制
信号量机制的问题:需要程序员实现,编程困难;维护困难;容易出错:wait/signal位置错、 wait/signal不配对。
解决方法:由编程语言解决同步互斥问题;管程(1970s, Hoare和Hansen)
信号量:分散式;管程:集中式
1.管程
管程示例:
管程功能:
互斥:
管程中的变量只能被管程中的操作访问
任何时候只有一个进程在管程中操作
类似临界区
由编译器完成
同步:
条件变量
唤醒和阻塞操作
2. 条件变量
condition x, y;
条件变量的操作:阻塞操作:wait;唤醒操作:signal
x.wait(): 进程阻塞直到另外一个进程调用x.signal()。
x.signal():唤醒另外一个进程。
条件变量问题:
管程内可能存在不止1个进程。 例如:进程P调用signal操作唤醒进程Q后。
存在的可能处理方式:
P等待,直到Q离开管程或等待另一条件(Hoare)。
Q等待,直到P离开管程或等待另一条件(Hansen)。
知识回顾
三、经典的进程同步问题
3.1生产者-消费者问题
生产者-消费者问题是相互合作进程关系的一种抽象。
利用记录型信号量实现:
假定,在生产者和消费者之间的公用缓冲池中,具有n个缓冲区,可利用互斥信号量mutex使诸进程实现对缓冲池的互斥使用;
利用资源信号量empty和full分别表示缓冲池中空缓冲区和满缓冲区的数量。
又假定这些生产者和消费者相互等效,只要缓冲池未满,生产者便可将消息送入缓冲池;只要缓冲池未空,消费者便可从缓冲池中取走一个消息。
其它解决方案:AND信号集、管程。
1.生产者-消费者问题描述:
生产者(M个):生产产品,并放入缓冲区
消费者(N个):从缓冲区取产品消费
问题:如何实现生产者和消费者之间的同步和互斥?
2.生产者消费者流程:
3.生产者消费者的互斥分析:
4.划分临界区:
5.增加互斥机制:
6.生产者消费者的同步分析:
7.算法描述:生产者、消费者
8.同步信号量定义:
共享数据:semaphore *full, *empty, *m; //full:满缓冲区数量 empty:空缓冲区数量
初始化: full->value = 0; empty->vaule = N; m->vaule = 1;
9.解决方法:
10.相邻P、V操作的顺序影响:
11.利用AND信号量解决生产者-消费者问题:
12.利用管程解决生产者-消费者问题:
知识回顾
3.2哲学家就餐问题
1.哲学家就餐问题描述:
五个哲学家的生活方式:交替思考和进餐;共用一张圆桌,分别坐在五张椅子上;在圆桌上有五个碗和五支筷子;平时哲学家思考,饥饿时便试图取用其左、右最靠近他的筷子,只有在拿到两支筷子时才能进餐;进餐毕,放下筷子又继续思考 。
解决方案:记录型信号量; AND信号量集、管程。
2.利用记录型信号量解决:
存在问题及解决方案:
可能引起死锁,如五个哲学家同时饥饿而各自拿起左筷子时,会使信号量chopstick均为0;因此他们试图去拿右筷子时,无法拿到而无限期等待。
解决方法:
最多允许4个哲学家同时坐在桌子周围;
仅当一个哲学家左右两边的筷子都可用时,才允许他拿筷子;
给所有哲学家编号,奇数号的哲学家必须首先拿左边的筷子,偶数号的哲学家则反之。
3.利用AND信号量机制解决哲学家就餐问题:
4.利用管程解决哲学家就餐问题:
3.3读者-写者问题
有两组并发进程:读者和写者,共享一组数据区。
要求:①允许多个读者同时执行读操作; ②不允许读者、写者同时操作; ③不允许多个写者同时操作。
分类:读者优先(第一类读者写者问题) ;写者优先(第二类读者写者问题)
解决方案:记录型信号量、信号量集
1.读者优先(第一类读者写者问题):
如果读者来:
无读者、写者,新读者可以读;
有写者等,但有其它读者正在读,则新读者也可以读;
有写者写,新读者等。
如果写者来:
无读者,新写者可以写;
有读者,新写者等待;
有其它写者,新写者等待。
2.写者优先(第二类读者写者问题):
问题描述:
多个读者可以同时进行读;
写者必须互斥(只允许一个写者写,也不能读者写者同时进行);
写者优先于读者(一旦有写者,则后续读者必须等待,唤醒时优先考虑写者)。
利用信号量集解决读者-写者问题:
关于信号量的讨论:
信号量的使用:
信号量必须置一次且只能置一次初值,初值不能为负数;
除了初始化,只能通过执行P、V操作来访问信】号量。
使用中存在的问题:死锁 、饥饿
互斥分析基本方法:
同步分析:
①找出需要同步的代码片段(关键代码);
②分析这些代码片段的执行次序;
③增加同步信号量并赋初始值;
④在关键代码前后加wait和signal操作。
信号量的物理含义:
S>0表示有S个资源可用;
S=0表示无资源可用;
S<0则| S |表示S等待队列中的进程个数。
P(S):表示申请一个资源;;
V(S)表示释放一个资源。信号量的初值应该大于等于0。
PV操作的使用:
P.V操作必须成对出现,有一个P操作就一定有一个V操作;
当为互斥操作时,它们同处于同一进程;
当为同步操作时,则不在同一进程中出现;
如果P(S1)和P(S2)两个操作在一起,那么P操作的顺序至关重要,一个同步P操作与一个互斥P操作在一起时同步P操作在互斥P操作前;
而两个V操作无关紧要。
信号量同步的缺点:
同步操作分散:信号量机制中,同步操作分散在各个进程中,使用不当就可能导致各进程死锁(如P、V操作的次序错误、重复或遗漏);
不利于修改和维护:各模块的独立性差,任一组变量或一段代码的修改都可能影响全局;
易读性差:要了解对于一组共享变量及信号量的操作是否正确,必须通读整个系统或者并发程序;
正确性难以保证:操作系统或并发程序通常很大,很难保证这样一个复杂的系统没有逻辑错误。
四、Linux进程同步机制
Linux并发的主要来源: (1)中断处理 (2)内核态抢占 (3)多处理器的并发。
同步方法:
1. 原子操作 2. 自旋锁(spin lock) 不会引起调用者阻塞 3. 信号量(Semaphore)
4. 互斥锁(Mutex) 5. 禁止中断(单处理器不可抢占系统)