本文共 2334 字,大约阅读时间需要 7 分钟。
进程同步
进程同步机制的主要任务,对多个相关进程在执行次序上进行协调,使并发执行的各进程之间按照一定的规则(或时序)共享系统资源,并能很好的相互合作,从而使程序的执行具有可再现性
共享资源可能会产生的俩种制约关系:
一.间接相互制约
多个程序并发执行(各进程在相同的时间间隔内(比如时间间隔按照时间片的大小)执行,不是同一时刻执行(同一时刻执行是并行执行,可以在多处理机上运用))
当要访问像打印机,磁带机这样的临界资源,必须要保证多个进程互斥的访问这些临界资源,这样便达到了间接互相制约的效果
临界资源:硬临界资源和软临界资源,必须互斥访问
把进入临界资源的代码称为临界区
访问临界资源的循环进程
while(TRUE){
进入区;//临界区之前的一段用于检出的代码
临界区;//如有进程在访问临界资源,需要将访问标志设置为正在访问
退出区;//将正在访问标志恢复为未被访问标志
剩余区;//除了进入区,临界区,退出区的代码之外的部分
}
二.直接相互制约
如输入进程A和计算进程B,它们之间共享一个缓冲区(引入缓冲区的主要原因:①缓和CPU与I/O设备间速度不匹配的矛盾②减少对CPU的中断频率,放宽对CPU中断响应时间的限制③解决数据粒度(数据单元大小)不匹配问题 ④提高CPU和I/O设备之间的并行性),进程A通过缓冲区向进程B提供数据,进程B从缓冲区提取数据,并对数据进行处理,当缓冲区为空时,进程B不能提取数据而堵塞(block),当进程A输入数据到缓冲区后变将进程B唤醒(wakeup),同样,当进程A不能向缓冲区输入数据时(即缓冲区满),进程A堵塞,当进程B向缓冲区提取数据后便将进程A唤醒。这样进程A和进程B便形成了直接相互制约关系
生产者(producer)-消费者(consumer)问题
int in=0,out=0,counter=0;
item buffer[n];//n个缓冲区的缓冲池
void producer(){
while(1){
produce an item in nextp;//每次生产的产品
....
while(counter==n)//判断是不是放满了
;
buffer[in]=nextp;//将产品放入到缓冲池中
in=(in+1)%n;//保证数组下标不越界 in的范围总是在0-n(不含n)中
counter++;
}
};
void consumer(){
while(1){
while(count==0)//判断是不是取完了
;
nextc=buffer[out];//从缓冲池取出产品
out=(out+1)%n;
counter--;
consumer the item in nextc;
.....
}
};
上述程序顺序执行时是正确的 而并发执行就会出现差错 因为他们可以同时共享变量counter
因为加上一把锁 保证互斥共享 如同数据库中的共享锁S(只能读 也称读锁)和排他锁X(可读可写 也称写锁)或Java线程同步机制一样 当线程进入run方法后便为其加上一把锁
等run方法执行完之后再将锁释放掉
因此 为保证正确 需要引入互斥信号量解决进程同步问题
三.经典进程的同步问题
生产者与消费者(用记录型信号量解决)
int in=0,out=0;
int buffer[n];//n个缓冲区的缓冲池
semaphore mutex=1,empty=n,full=0;//互斥信号量初始值为1 empty 和full为资源信号量
void producer(){
do{
producer an item nextp;
...
wait(empty);//申请空缓冲区
wait(mutex);//利用互斥信号量mutex实现各进程对缓冲池的互斥使用 这里是申请访问 申请成功便获得访问权限 其他进程不能进入该临界区
buffer[in]=nextp;//将产品放入
in=(in+1)%n;
signal(mutex);// 将信号量释放 此时其它进程此时可以进入该临界区进行申请访问
signal(full);//释放资源 空缓冲区现在放了产品进去 即 full+=1
//对于互斥信号量mutex来说 wait和signal(也叫p和v操作,都属于原子操作(要么全部做 要么不做 不可中断)) 它们必要在单个方法中成对出现
}while(TRUE);
}
void consumer(){
do{
wait(full);//申请有产品的缓冲区
wait(mutex);
nextc=buffer[out];//取出产品
out=(out+1)%n;
signal(mutex);
signal(empty);//释放资源 取走了产品 此时增加空缓冲区 即empty+=1;
consumer the item in nextc;
...
}while(TRUE);
}
void main(){
cobegin
producer();
consumer();
coend
}
生产者与消费者(用AND信号量解决)
只要把wait(empty)和wait(mutex)用Swait(empty,mutex)代替就行 它们是等价的
类似的Ssignal(mutex,full)代替signal(mutex)和signal(full)
哲学家问题
可以规定先让奇数号哲学家先拿他左边的筷子 再去拿右边的筷子 而偶数号哲学家则相反 这样能够避免死锁(产生死锁的四个必要条件:①互斥条件②请求保持条件(不能申请到新的资源又占着原先资源不放)③不可抢占条件④循环等待条件) 又能使哲学家进餐
转载地址:http://gqsni.baihongyu.com/