为什么引入进程同步
在多道程序环境下,进程是并发执行的,不同程序之间存在着不同的相互制约关系。为了协调进程之间的相互制约关系,引入了进程同步的概念
相关概念及注意事项
-
临界资源
一段时间内只允许一个进程使用的资源 -
同步
分析什么地方需要“同步关系”,即必须保证“一前一后”执行的两个操作 -
为禁止两个进程同时进入临界区,同步机制应遵循以下原则
空闲让进,临界区空闲时,可以允许一个请求进入临界区的进程立即进入临界区
忙则等待,当已有进程进入临界区时,其他视图进入临界区的进程必须等待
有限等待,对请求访问的进程,应保证能在有限的时间内进入临界区
让权等待,当进程不能进入临界区时,应立即释放处理器,防止进程忙等待
信号量
信号量机制是一种功能较强的机制,可用来解决互斥与同步问题,它只能被两个标准的原语(原语的特点是执行期间不允许被中断)P(S)和V(S)访问
实现
利用PV实现同步
- 分析什么地方需要“同步关系”,即必须保证“一前一后”执行的两个操作
- 设置同步信号量S,初始为0
- 在“前操作”之后执行V(S)
- 在“后操作”之前执行P(S)
利用PV实现互斥
- 设置互斥信号量S,初始为1
- 在互斥问题中,PV操作加紧使用互斥资源的行为
经典:生产者-消费者问题
问题描述
一组生产者进程和一组消费者进程共享一个初始为空,大小为n的缓冲区,只有缓冲区没满时,生产者才能把消息放入缓冲区,否则必须等待;只有缓冲区不空时,消费者才能从中取出消息,否则必须等待。由于缓冲区是临界资源,他只允许一个生产者放入,或一个消费者取出
关系分析
从最后一句可知生产者和消费者对缓冲区互斥访问
生产者和消费者有事一个相互协作的关系,只有生产者生产之后,消费者才能消费,也是同步关系
信号量设置
mutex互斥信号量,full用于记录缓冲池“满”,初值为0,empty记录“空的”缓冲区数,初值为n
semaphore mutex=1;
semaphore empty=n;
semaphore full=0;
producer(){
while(1){
produce an item in nextp;//生产数据
p(empty);
p(mutex); //互斥加紧
add nextp to buffer; //数据放进缓冲区
v(mutex); //互斥加紧
v(full);
}
}
consumer(){
while(1){
//两个p操作不可以互换,会发生死锁
p(full); //获取满缓冲区域单元,用于实现进程同步
p(mutex); //互斥
remove an item from buffer;
v(mutex); //夹紧
v(empty);
consume the item;
}
}