并发进程 - 操作系统概论

进程的顺序性

       目前使用的计算机基本上是冯 - 诺依曼(Von Neumann)式的结构,其基本特点是处理器按指令地址的指示顺序执行指令,这样的处理器称为 顺序处理器进程的顺序性 是指进程在顺序处理器上的执行是严格按序的,只有在前一个操作结束后才能开始后继操作。

       当一个进程独占处理器顺序执行时,具有两个特性:

  1. 封闭性。进程执行的结果只取决于进程本身,不受外界影响,与其执行速度无关。
  2. 可再现性。进程重复执行时,也必定获得同样的结果。

 

进程的并发性

       在多道程序设计系统中会同时存在许多进程,每一个进程都有顺序性。在单处理器的情况下,这些进程要竞争处理器,它们必须轮流占用处理器。但进程什么时候能占用处理器,能占用多长时间,这不仅取决于进程自身,还取决于进程调度策略。在一个进程的工作没有全部完成之前,另一个进程就可以开始工作,我们说这些进程是 可同时执行 的,或称它们具有 并发性,并且把可同时执行的进程称为 并发进程

       并发进程相互之间可能是无关的,也可能是有交互的。例如,为两个不同的源程序进行编译的两个进程,它们是并发的,但它们之间却是无关的。又如,一个计算问题中的输入进程、处理进程、输出进程是三个并发进程,每一个进程的执行都依赖另一个进程的进展情况,可见,它们是一组有交互的并发进程。进程并发执行时,执行结果与其执行的相对速度有关。如果输入进程尚未把一批数据全部读入,处理进程就对其加工的话,那么其结果就会出错。因此,进程的并发执行会破坏“封闭性”和“可再现性”,且有交互的并发进程一定共享某些资源。

 

与时间有关的错误

       一个进程运行时,经常由于自身原因或外界原因而被中断,且断点不是固定的。什么时候再占用处理器而运行,是和进程调度策略有关的。所以,进程执行的相对速度不由进程自己来控制,于是,就可能导致并发进程在共享资源时出现错误。

       例1. 有下面一个针对用户的计数程序,一个进程负责新增客户,一个进程负责丢失客户,用这两个进程(这里线程来模拟)来统计目前拥有的客户数,如果运行就会发现,结果一定是不可测的。

class Program
{
    static int Count = 0;
 
    static void Main(string[] args)
    {
        Thread t1 = new Thread(new ThreadStart(In));
        Thread t2 = new Thread(new ThreadStart(Out));
        t1.Start();
        t2.Start();
        Console.WriteLine(Count);
        Console.ReadLine();
    }
 
    static void In()
    {
        for (int i = 0; i < 10; i++)
        {
            int r1 = Count;
            r1 = r1 + 1;
            Thread.Sleep(1); // 模拟耗时操作,产生进程中断
            Count = r1;
            Console.WriteLine("新增一个用户,现有用户 " + Count + " 人");
        }
    }
 
    static void Out()
    {
        for (int i = 0; i < 10; i++)
        {
 
            int r1 = Count;
            r1 = r1 - 1;
            Thread.Sleep(1); // 模拟耗时操作,产生进程中断
            Count = r1;
            Console.WriteLine("失去一个用户,现有用户 " + Count + " 人");
        }
    }
 
}

       两个进程并发执行,又交替访问共享变量,没有保护机制,就会出现意外的结果。造成结果不正确的因素与进程被打断的时间和能占用处理器执行的时间有关,由这种原因造成的错误称为 与时间有关的错误。在购票系统中,当非常多的进程查询得知有剩余票时,但又还未来得及对剩余票数进行修改,会出现卖出去许多根本就不存在的票。

 

临界区

       并发线程中与共享变量有关的程序段称为 临界区。如果能保证一个进程进在临界区执行时,不让另一个进程进入相关的临界区执行,即各进程对共享变量的访问是互斥的,那么就不会造成与时间有关的错误。

       对若干个并发进程共享某一变量的相关临界区的管理有三个要求:

  1. 一次最多只有一个进程能够进入临界区执行,其他想进入临界区执行的进程必须等待。
  2. 任何一个进入临界区的进程必须在有限的时间内退出临界区,不能让其无限制的在临界区执行。
  3. 有进程退出临界区时,应让一个等待进入临界区的进程进入临界区执行。

 

PV 操作

       PV 操作能够实现对临界区的管理要求。它由“P 操作”和“V 操作”组成。它们是两个不可中断的过程,通常把不可中断的过程称为 原语。因此,P 操作和 V 操作也可称为 P 操作原语和 V 操作原语,简称 PV 操作。

       PV 操作是对信号量进行操作,它的定义如下:

  1. P 操作,P(S):将信号量 S 减去 1,若结果小于 0,则把调用 P(S)的进程置为等待信号量 S 的状态。
  2. V 操作,V(S):将信号量 S 加 1,若结果不大于 0,则释放一个等待信号量 S 的进程。(结果大于 0 的话,根本就无需释放任何其他进程,因为并没有进程阻塞在这里!)

       PV 操作是个难点,这里模拟一个具体的调用分析整个过程的步骤:

  1. 将信号量 S 的初始值定位 1。
  2. A,B,C,D 四个进程想要进入临界区执行,他们必须先调用 P 操作,于是,A 调用了 P 操作后,S 的值成为 0,A 可以进入临界区执行;B 调用 P 操作后,S 的值为 -1,由于小于 0,B 被设置为等待状态;以此类推,C,D 也进入等待状态,此时,S 的值为 -3。
  3. A 在临界区执行完毕,调用 V 操作,此时 S 的值为 -2(S = S +1),由于不大于 0,所以一定有其他线程在等待状态,就要释放一个等待信号量 S 的进程,让它继续执行。假设依照举例时约定的顺序,B 被唤醒。
  4. B 被唤醒后进入运行状态,此时 B 不会再调用 P 操作,会从先前调用 P 操作后中断的地方继续执行。执行完毕后,B 会调用 V 操作,此时 S 的值为 -1,由于不大于 0,继续释放一个等待信号量 S 的进程,C 被唤醒。
  5. 以此类推,D 执行完并调用 V 操作后,S 的值为 1,由于不大于 0 的条件不成立,所以得知没有任何其它进程在等待资源中,也就无需再释放任何信号,这次 4 个并发进程争夺资源的过程结束。

 

进程的互斥

       进程的互斥 是指当有若干个进程都要使用某一资源时,任何时刻最多只允许一个进程去使用该资源,其他进程必须等待,直到该资源的占用着释放了该资源。

       由于自身或外界的原因,进程执行时随时会被中断。那么,一个已进入临界区的进程在临界区执行时被打断,能否保证共享资源的互斥呢?回答是肯定的,因为该进程虽然被中断,但由于在临界区的执行还没有结束,因此不会调用 V 操作,而其他进程想要进入临界区,一定会先调用 P 操作,此时 S 的值一定不大于 0,所以结果必然是等待。

 

进程的同步

       进程的同步 是指在并发进程之间存在一种制约关系,一个进程的执行依赖另一个进程的消息,当一个进程没有得到另一个进程的消息时应等待,直到消息到达才被唤醒。

       事实上,PV 操作还是一个简单又方便的同步工具。用一个信号量与一个消息联系起来,当信号量的值为 0 时表示所期望消息还未产生,当信号量的值大于 0 时,表示所期望的消息已经存在。显然,任何进程只要调用 P 操作时就可测试自己所期望的消息是否已到达。

       在使用 PV 操作作为同步机制时,要根据具体的问题来定义信号量和调用 P 操作或 V 操作。一个信号量与一个消息联系在一起。当有多个消息时必须定义多个信号量。测试不同的消息是否到达或发送不同的消息时,应对不同的信号量调用 P 操作或 V 操作。

 

生产者 / 消费者 问题

       当搞清了生产者和消费者之间是怎样同步工作的,就可推广应用,解决其他许多同步问题。现假定有一个生产者和一个消费者,他们共用一个缓冲器,缓冲器中只能存入一件物品。显然,应该是生产1,消费1,生产1,消费1这样的节奏。用 PV 操作实现生产者与消费者的同步问题时,可以定义两个信号量:

  1. SP:表示是否可以把物品存入缓冲区。由于缓冲器中只能存放一件物品,所以 SP 初始值为 1。
  2. SG:表示缓冲器中是否存有物品,显然,它的初始值为 0。

       对生产者来说,生产一件物品后应调用 P(SP)来测试是否可以把物品存入缓冲器,当 SP = 1 时,调用 P(SP)后不会成为等待状态,可以继续执行,把物品存入缓冲器,调用了 P(SP)之后,SP = 0,若消费者尚未取走物品,而生产者又生产了一件物品欲放入缓冲器,这时调用 P(SP)将使生产者处于等待状态。当缓冲器存入一件物品后,应调用 V(SG)高速消费者缓冲器中有一件物品,调用 V(SG)后,SG 的值从 0 变为 1。

       对消费者来说,取走物品前应先调用 P(SG)查看缓冲器中是否有物品,当无物品时(SG = 0),调用了 P(SG)后,消费者就进入等待状态,当有物品时,调用 P(SG)后,消费者可继续执行取走物品,再调用 V(SP),通知生产者缓冲器中的物品已被取走,可以存入一件新的物品。

 

进程的互斥 & 进程的同步

       从进程互斥和进程同步的分析中,可以看到,进程的互斥实际上是进程同步的一种特殊情况。实现进程互斥时调用 P 操作测试是否可以使用共享资源,这相当于测试“资源已可使用”的消息是否到达。用 V 操作归还共享资源时,相当于发送“共享资源已空闲”的消息。所以,又经常把进程的互斥与进程的同步统称为 进程的同步,把用来解决进程的互斥与进程的同步的机制(如 PV 操作)统称为 同步机制

       但是,进程的互斥与进程的同步也是有差别的。进程的互斥是进程之间竞争共享资源的使用权,这种竞争没有固定的必然关系。而进程的同步就不同了,涉及共享资源的并发进程之间必然有一种依赖关系,当进程必须同步时,即使没有进程在使用共享资源,尚未得到同步消息的进程仍然不能去使用这个资源。

 

同步与互斥的混合问题

       若一组涉及共享资源的并发进程执行时不仅要等待指定的消息到达,而且还必须考虑资源的互斥使用,既要实现进程的同步,又要实现进程的互斥,这一类的问题就是同步与互斥的混合问题。

       例如,某工厂有一仓库可存放 8 台设备,生产部门生产的设备必须入库,销售部门可以从仓库提出设备卖给客户,入库与出库必须使用运输工具,现只有一套运输工具,每次只能运输一台设备。怎么设计一个能协调工作的调度管理系统?

       实际上,这是生产者和消费者的问题,系统的协调工作主要有两个方面:

  1. 仓库不满时才可以入库,仓库有设备才可以出库。
  2. 生产部门与销售部门需要竞争运输工具,以便完成各自的工作。

       显然,对于 1 ,两个部门需要互通消息实现同步,对于 2,两个部门要竞争共享资源实现互斥。用 PV 操作实现管理时应定义 3 个信号量,2 个用于互通消息,1 个用于控制设备的使用权:

  • S1:仓库中尚可存放多少设备,初始值为 8
  • S2:仓库中的设备数,初始值为 0
  • S:运输工具是否空闲,初始值为 1,表示空闲

       对共享资源仓库的操作应同步,需要互通消息,对运输工具的使用应互斥,程序流程为:

  • 生产部门:生产设备 - P(S1)- P(S) - 设备入库 - V(S) - P(S2)
  • 销售部门:P(S2) - P(S) - 设备出库 – V(S) - P(S1)

       注意 P 操作的次序,任何一个进程只有在得到自己所需的消息后,才能去竞争共享资源的使用权,即 P(S)一定要在 P(S1)或 P(S2)之后,否则会出现得到了使用共享资源的使用权却根本无法去使用的情况,整个系统就会瘫痪。(例如,生产部门拿到了运输工具,却因仓库已满而无法入库,被迫进入等待消息的状态;而消费部门可以出库却因为竞争不到运输工具,被迫进入等待状态,这就造成任何进程都不能工作。)

 

进程通信

       并发进程间可以通过 PV 操作交换信息实现进程的互斥与同步,因此可把 PV 操作看作是进程间的一种通信方式,但这种通信只交换了少量的信息(如缓冲器是否可以存入物品),只交换少量信息的通信方式是一种低级通信方式。有时,进程间需要交换大量的信息,大量信息的传递要有专门的通信机制来实现,这是一种高级的通信方式。

       通过专门的通信机制实现进程间交换大量信息的方式称为 进程通信。常用的高级通信方式有信箱通信、消息缓冲通信、管道通信等。下面介绍信箱通信方式。

  • 信件

       一个进程要向其他进程发送消息时,应先组织好一封信。信件的内容应包括:发送者名称(发送信件进程的名称)、信息(若信息量很大,可放在某个缓冲区中,这里指出缓冲区的起始地址和信息长度,这可以缩短信件长度,减少传递信件的时间)、等/不等 回信、回信存放地址。

  • 信箱

       接收信件的进程可以设立一个信息,信箱的大小决定了信箱中可以容纳的信件数,为便于了解信箱中的情况,信箱可以由“信箱说明(可存信件数、已有信件数、可存信件的指针)”和“信箱体(信件1,信件2..信件n)”两部分组成。

  • 通信原语

       用信箱实现进程间互通信息的通信机制要有两个通信原语:“发送(send)原语”和“接收原语(receive)”。

       send 和 receive 的功能以及实现要求如下:

  1. send(N,M):查指定信箱 N,若信箱未满,则按“可存信件的指针”把信件 M 存入信箱,且释放“等信件”者,若信箱已满,则把发送信件的进程置为“等信箱”状态。
  2. receive(N,Z):查指定信箱 N,若有信,则取出一封信存到指定地址 Z 中,且释放“等信箱”者,若无,则把接收信件进程置为“等信件”状态。

       一个进程要向其他进程发送信件时,必须先组织好信件,然后再调用 send 原语,且调用时需要给出参数,即信件发送到哪个信箱,以及信件的内容。进程调用 receive 原语接收信件时也要给出参数,即从哪个信箱取信,以及取出的信存放到哪里。

 

死锁

       计算机系统中优先的资源与众多的请求分配资源的作业和进程间会存在矛盾。若系统中存在一组进程(两个或以上),它们中每一个都占用了某种资源而又都在等待该组中另一个进程占用的资源,这种等待永远不能结束,则说系统出现了 死锁,这组进程处于 死锁状态

       死锁产生的原因:与资源分配的策略有关、与进程执行的速度有关。

       系统出现死锁必须同时保持下列 4 个必要条件:

  1. 互斥的使用资源。
  2. 占有且等待资源。
  3. 非抢夺式分配。
  4. 循环等待资源。

       必须强调,这四个条件仅仅是必要条件,而非充分条件。只要发生死锁,这四个条件一定同时成立,若其中有一个或几个条件不成立,则一定没有死锁。但反之则不然,即便这四个条件同时成立,系统未必就有死锁存在。

 

死锁的防止

       死锁的防止是指当采用某种资源分配策略后,使系统一定不会出现死锁。显然,如果采用的资源分配策略只要能破坏四个必要条件中的一个,则死锁就可防止。

       通常,使用的防止死锁的分配策略有:

  • 静态分配资源

       静态分配资源  是指进程必须在开始执行前就申请自己所要的全部资源,仅当系统能满足这个要求时,才会把这些资源分配给进程,该进程才开始执行。这个策略实现简单,但降低了资源的利用率。

  • 按序分配资源

       按序分配资源  是指对系统中每一个资源给出一个编号,规定任何一个进程申请两个以上的资源时,总是先申请编号小的资源,再申请编号大的资源。

  • 剥夺式分配资源

       剥夺式分配资源  是指当一个进程申请资源得不到满足时,可以从另一个进程那里去抢夺。这种资源分配策略目前只适用于处理器和主存资源的分配。

 

死锁的避免

       在防止死锁的分配策略中,剥夺式分配资源只适用于对某些资源的分配,静态分配资源会影响资源的利用率,而按序分配资源时,各进程使用资源的顺序往往与系统给资源的编号顺序不一致,这可能导致先申请到的资源在很长一段时间内闲置不用,也降低了资源的使用率。

       如不采用防止死锁的分配策略,则对资源的分配不能确保不产生死锁。但这时可采用如下办法:当估计到可能会产生死锁时,设法避免死锁的发生。只要系统能掌握并发进程中各个进程的资源申请情况,分配资源时就可先测试系统状态,分析会不会产生死锁,若把资源分配给申请者将产生死锁,则拒绝申请者的请求。

       一个古典的测试方法是银行家算法 是一个避免死锁的的著名算法,它以银行借贷系统的分配策略为基础,判断并保证系统的安全运行。银行家算法测试进程对资源的最大需求量,如果系统现存的资源可以满足时,就进行资源的分配,否则就推迟分配。这样的做法,能保证至少有一个进程可得到需要的全部资源而执行到结束,然后归还资源供别的进程使用。这个算法必须不断测试各个进程占用和申请资源的情况,需花费较多的时间。

       如果操作系统能保证所有的进程在有限时间内得到需要的全部资源,则称 系统处于安全状态,否则,就说 系统是不安全的

       例如,现有某类资源 12 个,3 个进程的分配情况如下表:

 

已占资源数

最大需求量

进程1

1

4

进程2

4

6

进程3

5

8

剩余资源数: 2

   

       此时,3 个进程又申请 1 个资源,由表中可以看出,若分给进程 1 和 3,系统是不安全的,剩余的 1 个资源已经不能满足任何一个进程的最大需求量了,因此,只能分配给进程 2。

 

死锁的检测

       不少系统并不是经常会出现死锁的,所以这些系统分配资源时不加特别的限制,只要有剩余资源,总是把资源分配给申请者。当然,这就有可能出现死锁,为解决死锁问题,这种系统设置了一个定时运行的“死锁检测程序”,当检测到死锁时再设法将其排除。

       死锁检测的一种方法是,设置两张表格来记录进程使用和等待资源的情况。例如,现有资源 R1 ~ R5,进程 P1 ~ P3,P1 需要 R153,P2 需要 R342,P3 需要 R25,三个进程并发执行,就可能出现下表的分配情况:

资源

占用进程

R1

P1

R2

P3

R3

P2

R4

P2

R5

P1

       现 P1 等待资源 R3,P2 等待资源 R2,P3 等待资源 R5,可以看出,P1 在等待 P2 释放资源,P2 等待 P3 释放资源,P3 等待 P1 释放资源,形成了相互等待的循环等待链,已经出现死锁。检测到死锁后,可采用抢夺某些进程占用的资源,或强迫进程结束、或重新启动操作系统等办法来解除死锁。

       在一个实际的操作系统中,为了安全和可靠,往往采用死锁的防止、避免和检测的混合策略,对不同的资源采用不同的分配策略,既考虑资源的使用效率,又保证整个系统不出现死锁。

 

TEST

1. 什么叫并发进程?

在多道程序设计系统中,往往同时有若干个进程请求执行,当一个进程的执行没有结束前,允许另一个进程开始工作,则说这些进程是同时执行的。可同时执行的进程被称为并发进程。

 

2. 临界区是怎样定义的?对相关临界区的管理应符合哪些要求?

在并发进程中与共享变量有关的程序段称为临界区,与共享变量有关的每个进程都有各自的临界区。对若干个并发进程共享某一变量的相关临界区的管理有三个要求:(1)一次最多只有一个进程能够进入临界区执行,其他想进入临界区执行的进程必须等待。(2) 任何一个进入临界区的进程必须在有限的时间内退出临界区,不能让其无限制的在临界区执行。 (3)有进程退出临界区时,应让一个等待进入临界区的进程进入临界区执行。

 

3. 采用 PV 操作作为同步机制时,假定与某共享变量相关的信号量 S 的值可在 [-1,1] 之间,问 S 的初始值是哪个值?当 S = -1,S = 0,S = 1时,它们各自的物理含义是什么?

S 的初始值为 1。当 S = 1 时,表示有一个共享资源可以被各进程访问;当 S = 0 时,表示已有一个进程正在临界区执行,其他进程必须进入等待状态;当 S = –1 时,表示有一个进程在等待进入临界区。

 

4. A,B 两个火车站是单轨连接,现在有许多列车同时到达 A 站,需经 A 站 到达 B 站,列车出 B 站后又可分路行驶。为保证行驶安全,请问应如何调度列车?请用 PV 操作为工具设计一个能实现你的调度方案的自动调度系统。

(1)A – B 段轨道是各列火车争夺的共享资源;只允许一列火车进入 A 站开往 B 站,其余火车必须等待;一列火车驶出 B 站后,释放信号让等待的火车进入 A 站并开往 B 站。

(2)设一个信号量 S,初始值为 1,表示只有一量火车可以进入 A 站并开往 B 站;各火车执行 P(S)操作,争夺到使用权的火车可以进入 A 站开往 B 站,其余火车都进入了等待状态;这列火车驶出 B 站后,执行 V(S)操作归还轨道的使用权,等待的火车又可以进入 A 站开往 B 站;以此类推,系统就能实现自动调度。

 

5. 今有三个并发进程 R、M 和 P,它们共享一个缓冲区。R 负责从输入设备读信息,每次读出一个记录,并把它存放到缓冲区中。M 对缓冲区中的记录进行加工。P 把加工后的记录打印输出。读入的记录经加工并取走后,缓冲区中又可存放下一个记录。请用 PV 操作作为同步机制写出它们并发执行时能正确工作的程序。

S1:表示是否可把读人的记录放到缓冲区,初始值为 1
S2:表示是否可对缓冲区中的记录加工,初始值为 0
S3:表示记录是否加工好并可以输出,初始值也为 0
 
begin
    S1,S2,S3:semaphore;
    S1:=l;S2:=S3:=0;
cobegin
    process R
        begin
            L1:读记录;
            P(S1);
            记录存入缓冲区;
            V(S2);
            goto L1;
        end;
    process M
        begin
            L2:P(S2);
            加工记录;
            V(S3);
            goto L2;
        end;
    process P
        begin
            L3:P(S3);
            输出加工后的记录;
            V(S1);
            goto L3;
        end;
coend;
end

 

6. 现有四个进程 R1、R2、W1 和 W2,它们共享可以存放一个数的缓冲器 B。进程 R1 每次把从磁盘上读入的一个数存到缓冲器 B 中,供进程 W1 打印输出。进程 R2 每次把从键盘上读入的一个数存到缓冲器 B 中,供进程 W2 打印输出。当一个进程把数存放到缓冲器后,在该数还没有被打印输出之前不准任何进程再向缓冲器中存数。当一个进程已把缓冲器中的数打印输出后,在缓冲器还没有存入一个新数之前不准任何进程再从缓冲器中取数打印。怎样用 PV 操作使这四个进程并发执行时能协调地工作?

分析题目可知,这四个进程是两个生产者与两个消费者共享一个缓冲器的问题。进程 R1 和 R2 要争夺缓冲器 B 向里面存入一个数,是进程互斥;而 R1 与 W1,R2 与 W2 是同步进程,它们之间应该进行信息通信。可设置下列 3 个信号量:

S - 缓冲器中是否可存入一个数,初始值为 1
S1 - 表示 R1 是否已向缓冲器中存入一个从磁盘上读入的数,初始值为 0
S2 - 表示 R2 是否已向缓冲器中存入一个从键盘上读入的数,初始值为 0
 
begin
    S,S1,S2:semaphore;
    S:=l;S1:=S2:=0;
cobegin
    process R1
        x1 : integer
        begin
            L1:从磁盘上读入一个数;
            x1 := 读入的数;
            P(S);
            B := x1;
            V(S1);
            goto L1;
        end;
    process R2
        x2 : integer
        begin
            L2:从键盘上读入一个数;
            x2 := 读入的数;
            P(S);
            B := x2;
            V(S2);
            goto L2;
        end;
    process W1
        y1 : integer
        begin            
            L3:P(S1)
            y1 := B;
            打印 y1 的数;
            V(S);
            goto L3;
        end;
    process W2
        y2 : integer
        begin            
            L4:P(S2)
            y2 := B;
            打印 y2 的数;
            V(S);
            goto L4;
        end;
coend;
end

 

7. 两个并发进程的程序如下,若 process A 先执行了 3 个循环,然后 process B 又并发执行了一个循环,写出可能出现的打印值。什么情况下会出现与时间有关的错误?请用 PV 操作实现同步,使两个并发进程能正确执行。

begin:
  N: integer;
  N := 3;
cobegin
  process A
    begin
      L1: N := N + 5;
          go to L1
    end;
  process B
    begin
      L2: print(N);
          N := 0;
          go to L2
    end;
coend;
end;

(1)打印出的值的是 18 或 23。这是因为 3 个循环后,N 的值为 18,此时 A 和 B 并发执行,如果先执行的是 A 中的 N := N + 5,再执行 B 中的 print(N),结果就为23,若先执行 B 中的 print(N),结果就为 18,这就产生了与时间有关的错误。

(2)可设置两个信号量 S1 和 S2:

S1 -  表示 process A 是否可以进入临界区执行 N := N + 5,初始值为 1

S2 -  表示 process B 是否可以进入临界区执行 print(N)进行打印,初始值为 0

A 进程先执行 P(S1),改变了 N 的值后执行 V(S2)通知 B 进程;B 进程先执行 P(S2),打印后再执行 V(S1)通知 A 进程。这就实现了两个进程间的同步,每加一次 5 就打印一次 N 的值。

 

8. 利用信箱进行通信的通信机制中,应设置哪些基本通信原语?它们的功能是什么?

(1)用信箱实现进程间互通信息的通信机制要有两个通信原语:“发送(send)原语”和“接收原语(receive)”。

(2)send(N,M):查指定信箱 N,若信箱未满,则把信件 M 存入信箱 N,且释放“等信件”者,若信箱已满,则把发送信件的进程置为“等信箱”状态。 receive(N,Z):查指定信箱 N,若有信,则取出一封信存到指定地址 Z 中,且释放“等信箱”者,若无,则把接收信件进程置为“等信件”状态。

 

9. 什么叫死锁?什么原因会引起死锁?

(1)若系统中存在一组进程(两个或以上),它们中每一个都占用了某种资源而又都在等待该组中另一个进程占用的资源,这种等待永远不能结束,则说系统出现了死锁,这组进程处于死锁状态。

(2)死锁的出现与资源分配策略、并发进程的执行速度有关。起因是系统提供的资源数比多个进程要求使用的资源少,这时,进程间就会出现竞争资源的现象,如果对这些资源分配不当的话就会引起死锁。

 

10. 有哪些策略可防止和避免死锁?

防止死锁的策略有:静态分配、按序分配、剥夺式分配。银行家算法可以避免死锁。

 

11. 某系统有输入机和打印机各一台。今有两个进程要同时使用它们。请写出采用 PV 操作实现请求使用和归还释放的程序。检查所写的程序会产生死锁吗?若否,请说明理由。若会产生死锁,则请适当修改程序以防止死锁。

设置两个信号量 S1 和 S2 分别表示输入机和打印机的使用权。各进程执行流程如下,就不会出现死锁。这种程序的编制方法,已经潜在的规定了各进程申请资源时,都是按照编号的顺序来申请资源,申请到输入机的进程就一定能申请到打印机,而另一个进程由于根本申请不到输入机,只能进入等待状态,所以也不可能申请到打印机。

S1 - 表示输入机的使用权,初始值为 1
S2 - 表示打印机的使用权,初始值为 1
begin
    S1,S2:semaphore;
    S1:=S2:=1;
cobegin
    process P1
        begin
            L1:
            P(S1);
            使用输入机;
            P(S2);
            使用打印机;
            V(S2);
            V(S1);
            goto L1;
        end;
    process P2
        begin
            L2:
            P(S1);
            使用输入机;
            P(S2);
            使用打印机;
            V(S2);
            V(S1);
            goto L2;
        end;
coend;
end

 

12. 设有 12 个同类资源可供 4 个进程共享,进程对资源的需求量及资源分配的情况如下表。问:(1)目前系统是否处于安全状态?为什么?(2)如果这 4 个进程又都要求系统再分配一个资源时,在什么情况下会引起系统的死锁?为什么?

进程

已占资源数

最大需求量

P1

2

4

P2

3

6

P3

4

7

P4

1

4

(1)已占资源数为 10,系统剩余的资源数为 2,能满足 P1 的最大需求量,此时,系统处于安全状态。

(2)如果这 4 个进程又都要求系统再分配一个资源时,当分配给 P2,P3,P4 时就会产生死锁。因为这 1 个资源被分配出去后,系统还剩余的 1 个资源将无法满足任何一个进程的最大需求量。

你可能感兴趣的:(并发进程 - 操作系统概论)