在操作系统引入进程后,一方面,系统中的多道程序可以并发执行,不仅有效改善资源利用率,而且显著提高系统的吞吐量。另一方面,如果不对多个进程的运行进行妥善管理,必然会因为这些进程对系统资源的无序争夺给系统造成混乱。此时我们引出进程的同步与互斥问题,互斥是同步的一种特殊情况。

例如,10个同学在食堂的同一个窗口买饭吃,如果大家不排队,谁抢先刷到卡,才可以拿到吃的,这属于同步问题中的间接相互制约关系—互斥。当同学们轮流刷卡吃饭时,属于同步问题中的直接相互制约关系—同步。

在实现进程的互斥与同步的过程中,我们主要会遇到三类方法:软件方法硬件方法信号量机制

在介绍这些方法之前,我们先来了解一下临界资源临界区的概念:

临界资源(Critical Resouce):临界资源是一次仅允许一个进程使用的共享资源。各进程采取互斥的方式实现对这种资源的共享,许多硬件资源如打印机、磁带机等,都是临界资源。就像一个女孩给你说:我有男朋友的时候,你们都撩不动我!

临界区(Critical Section):人们把每个进程中访问临界资源那段代码叫做临界区。每个进程进入临界区之前先对欲访问的临界资源进行检查,看是否正在被访问。如果此刻该资源未被访问,该进程可进入临界区,并设置它正在被访问的标志,在临界区之前执行的这段代码称为进入区(Entry Section),当然在临界区之后也要加上一段代码,用于将临界区被访问的标志恢复为未被访问的标志,称为退出区(Exit Section),代码中的其余部分叫做剩余区(Remainder Section)。

所有的同步机制遵循的四条准则:①空闲让进②忙则等待③有限等待④让权等待

前面三个好理解,没有人访问我的时候,你们尽管来,来者是客。在我被别人访问的时候,你就需要在外头静候。但是不能让你等到下辈子,这样做有点不大好看。

让权等待的意思就是既然你在外边不知道啥时候可以进来,那就先把自己阻塞(block)起来,等我空闲的时候会来把你唤醒(wake up)。免得你一直在外边敲门,还占着CPU不放。

我们开始介绍同步机制的软件实现方法:

1、单标志法:

设置一个公共变量turn,当turn=0时,P1进程中的while语句进入死循环,此时只有P0进程可以访问临界资源,当turn=1时同理。

单标志法通过两个while循环保证P0和P1不能同时执行,解决了临界区的互斥问题。

//p0进程                        p1进程
while(turn!=0);            while(turn!=1);     //进入区
critical section;       critical section;   //临界区
turn=1;                turn=1;                //退出区
remainder section;      remainder section;  //剩余区 

这么短,一看就不靠谱!turn变成了制约因素,P0、P1必须循环进入。若我P0进入一次临界区后,我不干了,摊牌了,没有我P0修改turn的值,那你P1这辈子也别想再进去。P1心里苦啊,受制于人!违背了空闲让进准则。

2、双标志法先检查:

采用两个标记flag[i]和flag[j]。类似于公共卫生间的挂牌,通过true的标记暗示你“有人”,阻止别人进入访问。

//pi进程                        pj进程
while(flag[j]);         while(flag[i]);     //进入区
flag[i]=true;          flag[j]=true;       //进入区
critical section;           critical section;   //临界区
flag[i]=false;         flag[j]=false;     //退出区
remainder section;      remainder section;  //剩余区

这样说好了吧,曾经受过制的P1说我终于可以连续使用了!可是当flag[i]=flag[j]=false时,两个进程同时进入了临界区。临界区表示,偶买噶!这和我们之前约定好的不一样。主要原因在于进入区检查和修改的操作不能一次进行完,违背了忙则等待准则。

3、双标志法后检查:

区别于双标志法先检查的地方在于将flag提到前面。

//pi进程                        pj进程
flag[i]=true;          flag[j]=true;       //进入区
while(flag[j]);         while(flag[i]);     //进入区
critical section;           critical section;   //临界区
flag[i]=false;         flag[j]=false;     //退出区
remainder section;      remainder section;  //剩余区 

小做修改,说这样子两个进程不会再同时进入临界区了吧。于是两个进程高高兴兴开始执行,每人运行了一行代码,卧槽!怎么都被关门外边了,一个人也进不去。最坏的这种情况就是这样,造成了死循环。

4、Peterson's Algorithm:

Peterson算法说,看你们这花里胡哨的,我来写个算法,把你们的思想结合一下,此类争论可以休矣!

//pi进程                        pj进程
flag[i]=true;turn=j;      flag[j]=true;turn=i;    //进入区
while(flag[j]&&turn==j);  while(flag[i]&&turn==i);//进入区
critical section;           critical section;       //临界区
flag[i]=false;         flag[j]=false;     //退出区
remainder section;      remainder section;      //剩余区       

在Peterson算法中,turn好比一把钥匙,进程Pi要访问进程时,它把钥匙交到进程Pj的手上,这是算法的核心思想。此时如果进程Pj正在访问临界资源,Pi就不能进入临界区。钥匙是公共变量,所以每次只能有一个进程进入。

所以遇到同步机制的软件实现方法的相关算法时,只要不是Peterson算法一定存在问题!

总结:从上面的方法中,我们可以看出,首先采用软件实现的方法始终不能解决忙等的现象,当一个进程在访问临界资源的时候,另一个进程一直在占用CPU,一直在不断“敲门”。此外他们通常实现两个进程的互斥,很难控制多个进程的互斥。

接下来我们介绍同步机制的硬件实现方法:

1、屏蔽中断:

由于进程切换需要依赖中断来实现,如果屏蔽中断则不会出现进程切换。为了实现对临界资源的的互斥使用,可以在进程进入临界区之前屏蔽中断,当进程退出临界区时,打开系统中断。中断被屏蔽以后,系统时钟中断也被屏蔽,处理机将不会被切换到其他进程,有效地保证了互斥。

想的有点美噢!中断被屏蔽以后,系统将无法响应任何外部请求,也不会响应当前执行进程的任何异常及系统故障,严重降低了处理机性能。其次这种方法仅对单处理机系统有效,如果系统有两个或多个共享内存的处理机,屏蔽中断仅仅对执行本指令的处理机有效,其他处理机仍将继续运行,并可以访问共享内存空间。

2、Test-and-Set指令实现互斥

利用一些专用硬件指令也能实现互斥,机器指令在一个指令周期内执行,不会受到其他指令的干扰,也不会被中断。

boolean testAndSet(boolean* lock){boolean old;old=*lock;*lock=true;return old;
}do{while(testAndSet(&lock));critical section;   //临界区 lock=false;          remainder section;  //剩余区
}while(true);

在进程访问临界资源之前,利用Test-and-Set检查和修改标志lock,若有进程在临界区,则反复检查,直到进程退出。

3、Swap指令实现进程互斥

该指令称为对换指令,用于交换两个字的内容。

void swap(boolean* a,boolean* b){boolean temp;temp=*a;*a=*b;*b=temp;
} do{key=true;do{swap(&lock,&key);//lock与key的值交换 }while(key!=false);//只有key为false时才能跳出,此时代表临界区没有被占用critical section;//临界区 lock=false;remainder section;//剩余区
}while(true);

实现的思想与上一个算法类似。

总结:硬件同步机制非常简单,同时适用于单处理机系统和共享内存的多处理机系统中多个进程互斥。但忙等现象仍然存在,并且有可能出现饥饿现象,当临界区空闲时,执行循环检测的若干个等待进程能进入临界区的概率相同,可能这时候有一个张三进程运气非常不好,很难进入临界区。

信号量机制:

这前面说这么多,都是为了引出信号量机制!也就是我们常常说的PV操作

信号量机制能够实现进程的互斥和同步,而不必忙等。

1、整型信号量

最初由Dijkstra把整型信号量定义为一个用于表示资源数目的整型量S,它与一般整型量不同,除此之外,仅能通过两个标准的原子操作(Atomic Operation)wait(S)和signal(S)来访问。

wait和signal可以被描述为:

wait(S){while(s<=0);s--;
}
signal(S){s++;
}

wait(S)和signal(S)是原子操作,执行是不可中断的。另外,在wait操作中,对S的测试和做S=S-1的操作时都不可中断,信号量只能通过原语操作来访问,不能被进程调度打断。

缺点:信号量S<=0时“忙等”,CPU释放不出来,未遵循“让权等待”。

2、记录型信号量

记录型信号量机制是一种不存在“忙等”现象的进程同步机制。哎呀!终于找到合适的方法了。

在“让权等待”的策略中,会出现多个进程等待访问同一临界资源的情况。为此,在信号量机制中,除了需要一个用于代表资源数目的整型变量value外,还应该增加一个进程链表指针list,用于链接等待进程。

typedef struct{int value;struct PCB*list;//list中每一项都代表一个PCB
}sempaphore;

相应的,wait(S)和signal(S)操作可以描述为:

wait(semaphore* S){S->value--;//请求一个该类资源if(S->value<0)//该类资源已分配完毕,调用block原语阻塞,插入到信号量链表中  block(S->list);
}signal(semaphore* S){S->value++;if(s->value<=0)wakeup(S->list);//注意这里是<=
}

注意,阻塞进程不会占用处理机时间,不是忙等。

wait操作用于申请资源(或使用权),进程执行wait原语时,可能会阻塞自己。signal操作用于释放资源(或归还资源使用权),进程执行原语时,有责任唤醒一个阻塞进程。

对信号量的每次signal操作,value++,若+1之后仍是S.value<=0,表示在该信号量链表中仍有等待该资源的进程被阻塞,则应调用wakeup原语,将链表中第一个等待进程唤醒。

用PV操作实现进程互斥时,互斥信号量的初值是1;用来实现进程同步时,资源信号量的初值由用户确定。

操作系统内核以系统调用形式提供wait和signal原语,应用程序通过该系统调用实现进程间的互斥同步。

信号量的应用:

1、利用信号量实现进程互斥

为使多个进程互斥地访问某临界资源,只需为该资源设置一互斥信号量mutex,并设置其初始值为1。

semaphore mutex=1;
//利用信号量实现进程互斥,mutex作为互斥锁使用
void P1(){                          void P2(){while(1){             while(1){P(mutex);                  P(mutex);critical section;          critical section;V(mutex);              V(mutex);}                  }
}                   } 

2、利用信号量实现前趋关系(同步)

semaphore s=0;
//semaphore s=2;
void P1(){                  void P1(){while(1){         while(1){P(s);          P(s);print(A);          print(B);V(s);          V(s);}              }
}               } 

当s=0时,可以出现AB、AABB、AAB(A必须先于B出现,且只可能A比B多或者A和B一样多)。

当s=2时,可能出现BBA(B可能出现的次数只能比A的最多多两个)。

下次整理一下用信号量机制实现的经典同步问题。

制作不易,多多点赞(●'◡'●)!

【操作系统·考研】信号量机制/PV操作相关推荐

  1. 操作系统复习——信号量与PV操作

    信号量与PV操作 问题的提出 TS或swap指令管理临界区,采用忙式轮询,效率低 关开中断管理临界区,不便交给用户程序使用 信号量的构思 一种可动态定义的软件资源:信号量 核心数据结构:等待进程队列 ...

  2. 【操作系统⑧】——信号量与PV操作(下)【哲学家进餐问题 AND型信号量 信号量集机制】

  3. 计算机操作系统pv实验,计算机操作系统笔记--信号量与PV 操作

    同步和同步机制 一个进程在某一特殊点上被迫停止执行直到接收到一个对应的特殊变量值,通过特殊变量这一设施,任何复杂的进程交互要求可得到满足,这种特殊变量就是信号量(semaphore).在操作系统中,信 ...

  4. 【系统架构设计师】第一章:操作系统(1.2.2) 信号量与pv操作

    本篇帖子继续上篇.有兴趣可以点击链接进行查看以前写过的文章. [系统架构设计师]第一章:操作系统(1.2.2) 参考教材: <系统架构设计师考试全程指导(第二版)> <系统架构设计师 ...

  5. 转 信号量与PV操作

    在计算机操作系统中,PV操作是进程管理中的难点. 首先应弄清PV操作的含义:PV操作由P操作原语和V操作原语组成(原语是不可中断的过程),对信号量进行操作,具体定义如下:     P(S):①将信号量 ...

  6. 小和尚挑水(信号量和PV操作)

     <--------个人网站传送门-------> 某寺庙,有小和尚.老和尚若干.庙内有一水缸,由小和尚提水入缸,供老和尚饮用. 水缸可容纳 30 桶水,每次入水.取水仅为1 桶,不可 ...

  7. 用户信号量及其PV操作处理实际问题

    P187-43 Cemaphore empty=1;橘子精=0;糖=0:水=0; Process product(){ While(true){ P(empty); 产生一个随机数s; If(s==0 ...

  8. 系统架构设计师考试知识点整理-3:信号量与PV操作

    出现场景 进程之间会出现互斥和同步两种关系.为了处理这两种情况,提出信号量和PV操作. 1.信号量:是一种特殊的变量,变现形式是一个整型S和一个队列. 2.P操作:S=S-1,若S<0,进程暂停 ...

  9. 顾客银行办理业务时,首先在取号机上取号,然后坐在椅子上等候业务员叫号时前往窗口办理业务,假设银行现在有3个窗口可办理业务,请采用信号量和PV操作描述顾取号等候叫号和银行业务员叫号办理业务的同步操作。

    顾客银行办理业务时,首先在取号机上取号,然后坐在椅子上等候业务员叫号时前往窗口办理业务,假设银行现在有3个窗口可办理业务,请采用信号量和PV操作描述顾取号等候叫号和银行业务员叫号办理业务的同步操作. ...

最新文章

  1. 2021年大数据常用语言Scala(十):基础语法学习 方法
  2. 50万买只波士顿动力机器狗,只为训练它“尿”啤酒,还让女朋友尝尝
  3. 详解图像直方图均衡化原理,附MATLAB、C、C++源码
  4. wpf中xaml的类型转换器与标记扩展
  5. C++字符串反转(C++11)
  6. 设计模式系列6:适配器模式(Adapter Pattern)
  7. sql xp_cmdshell
  8. git 回退上一个版本_Git小白使用教程:详细、显现、真正手把手教!
  9. PAT乙级——1001害死人不偿命的(3n+1)猜想(太简单)
  10. 南邮哈夫曼编码c语言代码_漫画:“哈夫曼编码” 是什么鬼?
  11. 为什么淘宝上同样的东西,专卖店比官方旗舰店便宜?
  12. 空巢青年,“空巢”是选择还是无奈? | 数据告诉你
  13. 【基本办公软件】万彩办公大师教程丨二维条码制作工具
  14. multisim怎么设置晶体管rbe_multisim晶体管
  15. 虚拟机安装过程中发生该错误:“客户机操作系统已禁用cup”问题解决方法【全】
  16. Nifi Api访问
  17. 计算机管理器磁盘清理,win10 磁盘空间清理管理器已停止工作怎么解决
  18. 3位1体学习法(smart哥)
  19. faker造假数据的使用
  20. 在eclipse上配置tomcat,安装eclipse的JST Server Adapters Extensions时报错 Anerroroccurredwhilecollectingitems...

热门文章

  1. 18版考研数据结构天勤课后习题代码-数组、矩阵与广义表【完】
  2. 【十三】景区人流量统计:python日志生成+logstash+kafka+storm+mysql+springBoot+高德地图
  3. JS 插件----SyntaxHighlighter的使用
  4. AutoCAD 2014 新特性--针对开发人员
  5. 无U 盘纯净安装Win10
  6. MySQL 语句大全
  7. 前端面试题(中高级)
  8. iSkysoft PDF Editor 6 pro安装
  9. kafka Java客户端之 consumer API 多线程消费消息
  10. 小程序申请体验版生成二维码