锁、PV操作、进程互斥与同步的实现

什么是临界区?

每个进程中访问临界资源的那段程序称为临界区(临界资源是一次仅允许一个进程使用的共享资源)。每次只准许一个进程进入临界区,进入后不允许其他进程进入。

一、锁机制:

1、锁:

在多线程编程中,操作系统引入了锁机制。通过锁机制,能够保证在多核多线程环境中,在某一个时间点上,只能有一个线程进入临界区代码,从而保证临界区中操作数据的一致性。

加锁过程用如下伪码表示:
1、read lock;
2、判断lock状态;(0表示资源可用,1表示资源已被占用)
3、如果已经加锁,失败返回;
4、把锁状态设置为上锁;
5、返回成功。

原语:是由若干个机器指令构成的完成某种特定功能的一段程序,具有不可分割性,即原语的执行必须是连续的,在执行过程中不允许被中断

上锁原语:

lock:(w锁位为1,表示已上锁)
{
    while(w == 1)
    {
        保护现场进程CPU现场;
        将现行进程的pcb插入w的等待队列;
        置该进程为“等待”状态;
        转进程调度;
    }
    w = 1;       //上锁
}

开锁原语:

lock:(w锁位为1,表示已上锁)
{
    while(w等待队列不为空)
    {
        移除等待队列首元素;
        将现行进程的pcb插入w的就绪队列;
        置该进程为“就绪”状态;
    }
    w = 0//开锁
}

上锁转到等待状态(也就是阻塞)。
开锁转到就绪状态(也就是就绪)。
这里写图片描述

进程的pcb(Process Control Block))系统为了管理进程设置的一个专门的数据结构,用它来记录进程的外部特征,描述进程的运动变化过程。系统利用PCB来控制和管理进程,所以PCB是系统感知进程存在的唯一标志。进程与PCB是一一对应的)


2、死锁:

死锁的原因:
(1) 因为系统资源不足。
(2) 进程运行推进的顺序不合适,保证有先后顺序。
(3) 资源分配不当等。

死锁的必要条件.
产生死锁的四个必要条件:
(1) 互斥条件:一个资源每次只能被一个进程使用。
(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3) 不剥夺条件: 进程已获得的资源,在末使用完之前,不能强行剥夺。
(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。存在一个进程等待序列{P1,P2,…,Pn},其中P1等待P2所占有的某一资源,P2等待P3所占有的某一 源,……,而Pn等待P1所占有的的某一资源,形成一个进程循环等待环。

解决死锁的四个方式.
1)忽略该问题。例如鸵鸟算法,该算法可以应用在极少发生死锁的的情况下。为什么叫鸵鸟算法呢,(鸵鸟策略)
2)检测死锁并且恢复。(检测与解除策略)
3)仔细地对资源进行动态分配,以避免死锁。(避免策略)
4)通过破除死锁四个必要条件之一,来防止死锁产生。(预防策略)


二、信号灯和P、V操作

1、信号灯:

信号灯是一个二元数组(s,q)。可以这么理解s信号灯的状态(一个整数),s的初值不为负数(和交通灯类似)。q是它的等待队列,建立信号灯时q为空。

  • s >=0 : 绿灯
  • s < 0 :红灯

2、P、V操作:

对信号灯状态进行改变,P调用一次-1,V调用一次+1。

P操作:
p(s)是一个原语操作,p操作执行 s– ,若s为负数,调用p(s)的进程被阻塞,放到等待队列q中。

p(s)
{
    s- -;
    if (s < 0)
    {
        保留调用进程的CPU现场;
        将进程的pcb插入到s的等待队列;
        把进程变为“等待状态”;
        转到进程调度;
    }
}

V操作
v(s)刚好与p(s)操作相反,v操作执行 s++ ,若s为大于0,继续执行;s <=0,从信号灯等待队列移出一个进程,解除等待状态,返回本程序继续执行。

v(s)
{
    s++;
    if (s <= 0)
    {
        移出s等待队列首元素;
        将该进程的pcb插入就绪队列;
        设置该进程为“就绪状态”;
    }
}

三、进程互斥的实现

这里写图片描述

上锁原语顺利通过可进入临界区CSa或者CSb。

1、使用上锁原语与开锁原语解决并发进程互斥问题:

main()
{
    int w = 0;    //互斥锁
    cobegin
        ppa();
        ppb();
    coend
}

ppa()               ppb()         
{                   {
    .                   .
    .                   .   
    .                   .
    lock(w);            lock(w);
    CSa;                CSb;
    unlock(w);          unlock(w);
    .                   .
    .                   .
    .                   .
}                   }

2、使用信号灯实现进程互斥:

  用与互斥信号灯初值mutex = 1 ;表示该资源未被占用。任何想要进入临界区的进程,必须先进行p操作(mutex为1时才能通过),访问临界资源完成后再v操作。。。

  • mutex =1 : 表示没有进程进入临界区
  • mutex =0 : 表示有一个进程进入临界区,前方没有其他进程。
  • mutex =-1 :表示一个进程已经进入,另一个进程的等待进入。
main()
{
    int mutex = 0;    //互斥信号灯
    cobegin
        Pa();
        Pb();
    coend
}

Pa()                Pb()         
{                   {
    .                   .
    .                   .   
    .                   .
    p(mutex);       p(w);
    CSa;            CSb;
    v(mutex);       v(mutex);
    .                   .
    .                   .
    .                   .
}                   }

四、进程同步实现:

实例:生产中消费者问题:

这里写图片描述

  • 消费者:消耗系统资源。
  • 生产者:释放系统资源。

缓冲区未空:消费者就可以一直取资源。
缓冲区未满:生产者就可以一直生产资源。
因此,同步关系保证了上面两点的实现。

方法:用两个信号灯,分别说明缓冲区数目(full和empty)

main()
{
    int w = 0;        //满缓冲区的数目
    int empty = n;    //空缓冲区的数目
    int mutex = 1;    //对有界缓冲区进行操作的互斥信号灯
    cobegin
        P1();P2()……Pm();
        C1();C2()……Cn();
    coend
}

producer()                          consumer()         
{                                   {
    while(生产未完成)                    while(还要继续消费)       
    {                                   {
        .                                   p(full);
        .                                   p(mutex);       
        .                                   从有界缓冲区取产品;
        生产一个产品;                     v(mutex);
        p(empty);                           v(empty);
        p(mutex);                           .
        送一个产品到有界缓冲区;                .
        v(mutex);                           .
        v(full);                            消费一个产品;
                                        }
    }                               }

}                       

生产者消费者代码参考:生产者消费者问题编程实例

  • 10
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值