一,进程同步
进程异步:各自并发执行的进程由于各自是独立的,所以会以不可预知的速度先前推进,就是你不能提前预料到它们将来是怎么执行的。
进程同步:它是指为了完成某个任务而建立起的两个或多个进程,这些进程在完成任务时,需要协调它们之间的执行顺序。
例如:进程通信的管道通信:
读进程必须要等到写进程写满管道才能开始读,写进程也必须要等到读进程读完管道数据才能开始写。这就是进程同步的一个例子。
二,进程互斥
临界资源:我们把同一时间内只允许一个人进程使用的资源叫做临界资源。例如打印机,摄像头。
而对临界资源的访问,必须要互斥地访问。
进程互斥:当一个进程访问临界资源时,另一个进程想访问临界资源就必须等待。等第一个进程访问完,第二个进程才能去访问。
三、实现进程互斥需要遵守的规则
1.空闲让进:临界区空闲时,可以允许一个请求访问临界区的进程立即访问临界区。
2.忙则等待:当已经有进程进入临界区时,其他想访问临界区的进程必须等待。
3.有限等待:对请求访问临界区的进程,应保证其能在 有限的时间内进入临界区。(保证不会饥饿)
4.让权等待:当进程不能进入临界区时,应立即释放处理机(cpu),防止进程忙等待。
教科书中提出了进程互斥的四个方法,分别是:
单标志法,双标志先检查法,双标志后检查法,皮尔森法,但没有一种能完全满足上述的四个条件。因此就直接讲信号量了。
四、信号量机制
信号量就是我们常说的P,V操作。
原语:原语指的是不可能被中断的操作。在信号量机制中,有wait(S),signal(S)原语,简称为P(S),V(S)操作。
信号量:信号量其实就是用于记录临界资源的变量。信号量分为整型信号量和记录型信号量。前者也是有一定缺陷的,就是不满足让权等待,例如:
我们可以看到下图,wait(int S)里,当S小于等于0时,程序是调用while语句来使程序循环等待的,但我们知道,调用while其实也是在cpu上运行的,因此进程在等待的过程中并没有释放处理机而是一直继续占用着,这就违背了“让权等待”的规则。
因此,为了解决这个问题,信号量不能仅仅是个整型变量,而是要是个还拥有其他功能信号量。这种信号量就叫做记录型信号量。
由下图可以看到,信号量是一个结构体,不仅包括资源个数value,也包括了一个队列 L。
具体使用例子如下:
在使用临界资源前,调用wait(S),把S的资源数减一,然后使用完后,再调用signal(S),把资源数加一,若资源数小于等于,则调用wait的进程会阻塞,并挂到S的阻塞队列中,等到唤醒。
1.用信号量实现进程同步
进程同步即说明多个进程(假设2个),必须要一前一后有顺序的执行。
为什么信号量初始要为0?因为必须要阻塞后操作的进程,让前操作的进行先运行,才能开放给后操作进行运行。
2.信号量实现互斥
跟信号量实现进程同步不同的是,实现互斥时,信号量初始为1。很容易理解,因为互斥的话,肯定一开始要开放临界区给各个进程访问的,但是一旦访问,就把信号量的值减一,互斥信号量一般用mutex表示。
五、哲学家问题(同步与互斥的例子)
要分析哪些问题需要互斥,哪些问题需要同步。
例如:
1.拿起筷子时,得互斥,一次只能一个人拿
2.筷子是一种信号量资源,共5个筷子,若是其中一个小于等于0(即被拿了),则其他进程调用时(拿起该筷子),会阻塞。
具体算法如下:
---------------------
基于王道。