进程互斥与同步
(1)
并发处理:排队等候、唤醒、执行
并发(宏观):在同一时间内,可以处理多个活动的能力,并发不一定并行。一个CPU在若干道程序实现。
并行:在同一时间内,同时发生事件。多个程序在不同CPU上同时执行。
(2)
进程间关系:竞争关系、协作关系。策略:进程同步、进程互斥、
(3)
进程同步:并发进程在某个条件下协调完成共同任务。
进程互斥:逐次使用互斥共享资源,也是一种并发进程协调完成共同任务。
(4)
在竞争资源里的死锁和饥饿:
死锁:永远等待资源。两个进程是同步的,发生资源冲突,两个进程都无法实现。
饥饿:因为优先级问题,调度的程序无限延期不能执行。异步的,永远在等待前面优先级高的进程释放资源。
(5)
临界区:并发进程与共享变量有关的程序段。
临界资源:被多线程同时访问的一份资源
访问冲突:1.一次只有一个进程可进入临界执行。2.已有进程时让其它试图进入的进程等待 。 3.进入临界的进程有限时间内退出
总结:互斥使用,有空让进。忙则要等,有限等待。择一而入,算法可行。
(6)
信号量:大于0表可用资源数;小于0表被阻塞进程数。
(7)
可重复调用的PV:
子函数BP、BV
先建立S记录型的数据结构,然后建立BP和BV子函数
S记录型数据结构:定义value值(0或1),和等待信号量进程队列list
typedef struct binary_semaphore{
int value;
struct pcb*list;
}
BP:导入记录S,判断S记录下的value值,为1则让value的值为0表示有进程进入临界,否则让进程进入等待队列沉睡
void BP(binary_semaphore s){
if(s.value==1)
s.value=0;
else
sleep(s.list);
}
BV:导入记录S,判断S记录下的value值 ,若等待队列为空,让value为1表示无进程进入临界。否则,唤醒等待队列中的进程。
void BV(binary_semaphore s){
if(s.list is empty)
s.value=1;
else
wakeup(s.list);
}
/五个哲学家吃面问题/:两个信号量
main:定义一个数组将5个哲学家依次放入数组,并附初值为1(for 循环)
依次放入进程:当数组不为空时,哲学家想就餐就要依次进行抢左边和右边的两把叉子,即调用两次BP子函数。
之后吃完再放下左边和右边的叉子,即调用两次BV子函数进行资源释放。
semaphore fork[5];
for(int i=0;i<5;i++){
fork[i]=1;
}
cobegin
process philosopher_i(){
while(true){
think();
P(fork[i]);
P(fork[(i+1)%5]);
eat();
V(fork[i]);
V (fork[(i+1)%5]);
}
}
coend
/一个超市有n个顾客购物,只有一个收银员/ 收银员:一个信号量、n个顾客:数组大小,进程数目
main:定义一个数组空间为n的数组,将n个顾客依次放入。
依次放入进程:当数组不为空时,顾客想要结帐需要等待收银员空闲,即调用一次BP子函数。
之后结完帐,调用一次BV子函数,表示收银员空闲。
semaphore fork[n];
for(int i=0;i<n;i++){
fork[i]=1;
}
cobegin
process philosopher_i(){
while(true){
think();
P(fork[i]);
check();
V(fork[i]);
}
}
coend
浙公网安备 33010602011771号