进程同步机制

进程同步概念

  • 概念:并发进程在一些关键点上可能需要互相等待或互通消息,这种相互制约的等待或互通消息称为进程同步。
  • 同步机制应遵循的准则
    • 空闲让进:其他进程均不处于临界区;
    • 忙则等待:已有进程处于其临界区;
    • 有限等待:等待进入临界区的进程不能"死等";
    • 让权等待:不能进入临界区的进程,应释放CPU(如转换到等待状态)

 

使用软件算法实现互斥

  • 算法1:两个进程P0, P1共享某临界资源
    • 算法一:设立一个公用整型变量 turn,描述允许进入临界区的进程标识,假设初始化turn=0,表示首先轮到P0访问临界资源

      • 该算法,初始化是设置的等待 P0 对进程进行访问,但是如果 P1 先申请访问就不能执行,违背了空闲让进的准则。
      • 当 turn 值为1时,如果 P0 进程想要访问临界资源,会在 while 语句中执行空循环等待,知道 turn 变为 0。所以当 P0 不能拿到访问权时,并没有放弃等待,而是一直占着 CPU 在做空循环等待,违背了让权等待的准则。
    • 算法二:设立一个标志数组flag[2]:描述进程是否已在临界区,初值均为0(FALSE),表示进程都不在临界区。

      • 在这个算法中,当 flag[1] = 0 的时候,我们可以进入 P0 进程,当 P0 进程刚执行完第一条 while 语句的时候,它的时间片到了, 中断 P0 进程的执行,进而执行 P1 的时候,又会因为 flag[0] = 0,认为临界资源可以访问,这样 P0 和 P1 都会同时访问临界资源。违背了忙则等待的原则
      • 当 flag[1] 为 1 的时候,P0 进程的 while 语句会执行空循环等待,所以也违背了让权等待的原则。

 

使用锁机制实现互斥

  • 锁的定义:用变量w代表某种资源的状态,w称为“锁” 。
  • 上锁操作和开锁操作
    • 上锁操作(临界资源的申请操作):
      • 检测w的值 (是0还是1);
      • 如果w的值为1,继续检测;
      • 如果w的值为0,将锁位置1 (表示占用资源),进入临界区执行
    • 开锁操作(临界资源的释放操作):
      • 临界资源使用完毕,将锁位置0
  • 上锁原语和开锁原语
    • 上锁原语
lock(){   
test:    if (w为1)
             goto  test;      ∕* 测试锁位的值*∕
         else w=1;
}   ∕*上锁*∕   	
    • 开锁原语
unlock(){ 
    w=0;
}   ∕*开锁*∕         
  • 操作方法
    • 加锁操作 -》 执行临界区程序 -》 开锁操作

 

信号量机制

  • 信号量数据结构的定义
typedef struct{
    int  value; /*信号量的值*/
    PCB * L;   /*进程等待队列队首指针*/
} semaphore ;             
    • value:初始化为一个非负整数值,表示空闲资源总数--若为非负值表示当前的空闲资源数,若为负值其绝对值表示当前等待临界资源的进程个数。
    • L:初值为空
  • 信号量的P、V操作: semaphore *S;
    • P 操作(临界资源申请操作)
P(S){
    S->value--;
    if(S->value<0) 
        sleep(S->L);  // 由于进程在不能申请到临界资源时是主动释放CPU并且阻塞到L链表上
                      // 所以信号量实现了让权等待的机制
}              
    • V 操作(临界资源释放操作)
V(S){
    S->value++;       // 归还一个临界资源给系统
    if(S->value<=0)
        wakeup(S->L); // 唤醒进程

}

 

利用信号量机制实现进程互斥与同步

  • 实现互斥
    • 为临界资源设置一个互斥信号量 mutex ,其初值为 1:
semaphore  mutex=1
    • 在每个进程中将临界区代码置于P(mutex)和V(mutex)原语之间:

    • 算法描述如下:

    • 给出一个例子:两个进程共享一台打印机

      • 在执行 Pa 进程的过程中,P 操作先对 mutex 减一,得到 0。不是负数,可以直接执行。 Pb 进程如果在这个时候进行申请,此时执行 P 操作,mutex 得到 -1,会阻塞 Pb 进程。
      • 当执行 Pa 进程的 V 操作时, mutex 值为 -1,加 1 得到 0。小于等于 0,唤醒等待进程 Pb。
      • 当 Pb 进程执行到 V 操作时, mutex 加 1 得到 1,此时打印机空闲。
  • 实现同步:进程间合作的前驱后继关系
    • 为一个同步关系设置一个同步信号量S,其初值为0:
semaphore  S=0       // 表示令牌
    • 前驱进程完成操作后执行V(S):表示释放令牌;后继进程开始操作前执行P(S):表示申请令牌
    • 算法描述:Pa -> Pb

    • 举个例子: I -> C -> P

    • 再举一个例子:对给出的前驱图编写同步信号量程序:

a,b,c,d,e,f,g:semaphore=0,0,0,0,0,0,0
cobegin 
       s1:   { s1;  v(a);  v(b);}
       s2:   { p(a);  s2;  v(c);  v(d);}
       s3:   { p(b);  s3;   v(e); }
       s4:   { p(c);  s4;   v(f); }
       s5:   { p(d);  s5;   v(g); }
       s6:   { p(e);  p(f);  p(g);  s6; }
coend 
    • 最后,再给出一个司机和售票员的例子,司机和售票员的工作进程如下:

      • 我们,首先需要寻找这两个进程之间的同步关系,得到同步关系如下:
        • 售票员关闭车门→ 司机启动车辆
        • 司机到站停车→ 售票员打开车门
      • 对于这连个同步关系,我们设置相应的同步信号量如下:
        • semaphore drive_sem={0,NULL};
        • semaphore conductor_sem={0,NULL};
      • 最后,我们根据这些信号量的设置,写出相应的算法如下:

  • 使用信号量解决进程同步问题的步骤
    • 确定进程:
      • 包括进程的数量、进程的工作内容。
    • 确定进程同步互斥关系:
      • 根据进程间是竞争临界资源还是相互合作处理上的前后关 系,来确定进程间是互斥还是同步。
    • 确定信号量:
      • 根据进程间的同步互斥关系确定信号量个数、含义、初始值,各进程需要对信号量进行的PV操作。
    • 用类程序语言描述算法。
  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值