之前说了那么多互斥,现在来说一说进程同步,但是,看字面意思,你是不是认为同步应该就是与互斥相反,可以允许多个进程访问同意资源,而且是一起?虽然可能只有我那么天真,但是答案是NO!
所谓进程同步,简单的说是“你等我,我也等你”的同步约束。其实是另外一种互斥,互斥是两者只能运行其一,没有顺序要求,但是同步,也是只能有一个进程访问资源,但是,顺序定了。
来看一下比较官方的解释:指的是两个或多个进程为了合作完成同一个任务,在执行速度或某些个确定的时序点上必须相互协调,即一个进程的执行依赖于另一个进程(其合作伙伴)的消息,当一个进程到达了某一确定点而没有得到合作伙伴发来的“已完成某些操作”的消息时必须等待,直到该消息到达被唤醒后,才能继续推进。
这是源于进程合作之间的制约关系,也称为直接制约关系。
既然互斥和同步那么相似,必然也会出现死锁的问题,如何解决?还是信号量机制,那个强大的P,V操作。
P操作和V操作的作用前面已经说过,就不在此赘述了。
在一个栗子中感受一下P操作和V操作在进程同步中的作用:
经典的生产者与消费者的问题:
一组生产者进程通过一个具有N个缓冲区的缓冲池循环不断的向一组消费者进程提*品的问题。
这个问题的同步关系的体现是:一旦缓冲池中的所有缓冲区都装满产品时,生产者必须等待消费者提供空缓冲区,一旦缓冲池为空,消费者必须等待生产者提*品。这里就出现两个“你等我,我也等你”的点了,用P,V操作来解决。
然后还要考虑一下互斥的问题,就是缓冲池的物品的存取是互斥操作。
生产者i:
生成出一产品;
P(empty);//表示有empty个空缓冲区可用
P(mutex);// mutex初值为1,以保证互斥使用缓冲池
将该产品放入到缓冲区;
V(mutex);//唤醒阻塞进程(类似进程互斥)
V(full);//表示有full个满缓冲区可用
消费者j:
P(full);//表示有full个慢缓冲区可用
P(mutex);// mutex初值为1,以保证互斥使用缓冲池
从缓冲区取出一产品;
V(mutex); //唤醒阻塞进程(类似进程互斥)
V(empty); //表示有empty个空缓冲区可用
消费该产品;
部分变量的说明:
同步信号量empty,初值为n,表示消费者已把缓冲池中全部产品取走,有n个空缓冲区可用。
同步信号量full,初值为0,表示生产者尚未把产品放入缓冲池中,有0个满缓冲区可用。
互斥信号量mutex,初值为1,以保证同时只有一个进程能够进入临界区,访问缓冲池。
如果一开始生产者进程抢先执行,则因为缓冲池全空,它生产出产品并执行P(empty)后能继续下去,直至缓冲池全满时,将会阻塞在empty信号量上,等待消费者执行V(empty)来唤醒自己。如果一开始消费者抢先执行,则因为缓冲池全空,它首先因执行P(full)而阻塞,直至缓冲池中有产品为止。就这样,生产者和消费者进程在并发执行过程中,时而你等我,时而我等你,同步的向前推进。而他们想要进缓冲区执行P(mutex),出缓冲区之后执行V(mutex),保证了对缓冲区的互斥使用。