📜  门| GATE-IT-2004 |问题11(1)

📅  最后修改于: 2023-12-03 15:28:46.082000             🧑  作者: Mango

门(GATE-IT-2004)问题11

这是一道关于进程同步的问题。假设有三个进程,分别为P1、P2和P3,它们共享一个共享整数变量S。以下是三个进程的伪代码:

P1:
    while True:
        x = random_int()
        sleep(2)
        S = S + x

P2:
    while True:
        y = random_int()
        sleep(3)
        S = S - y

P3:
    while True:
        sleep(1)
        print(S)

其中,random_int()是一个返回随机整数的函数,sleep(n)代表进程休眠n秒。

显然,这三个进程的执行顺序是不确定的,可能出现各种结果。但是,我们希望进程P3总能输出S的正确值。因此,需要对进程进行同步。

请你设计出一种同步机制,让P3能够正确地输出S的值。并给出相应的代码实现。同时,解释该同步机制是如何工作的。

同步机制

可以使用信号量来实现同步,做法如下:

首先,为S和一个二元组(empty, mutex)分别初始化两个信号量。其中,empty代表S是否为空,mutex是一个互斥信号量,用于保证在修改S时不会有其他进程同时修改。

接着,在进程P1中使用down(empty)判断S是否为空,若为空则进程进入等待状态。否则,执行down(mutex)获得互斥锁后,将生成的随机数加到S上,并释放互斥锁和信号量empty。

在进程P2中同理,使用down(empty)down(mutex)判断S是否为空及获得互斥锁后,将生成的随机数从S中减去,并释放互斥锁和信号量empty。

在进程P3中,首先使用down(empty)判断S是否为空,若为空则进程进入等待状态。否则,直接输出S的值即可。

代码实现
from threading import Semaphore
import time

S = 0
empty = Semaphore(0) # 用于判断S是否为空,初值为0
mutex = Semaphore(1) # 用于保证修改S时的互斥,初值为1

def P1():
    global S
    while True:
        x = random_int()
        time.sleep(2)
        empty.acquire()
        mutex.acquire()
        S = S + x
        mutex.release()
        empty.release()

def P2():
    global S
    while True:
        y = random_int()
        time.sleep(3)
        empty.acquire()
        mutex.acquire()
        S = S - y
        mutex.release()
        empty.release()

def P3():
    while True:
        empty.acquire()
        print(S)
        empty.release()

工作原理

当进程P1和P2执行的时候,它们首先会判断S是否为空。如果为空,则进入等待状态,直到另一个进程完成了对S的修改,并分配了一个信号量empty,P1和P2才能继续执行。接着,它们会申请互斥锁mutex,确保在修改S的过程中,不会有其他进程同时修改,从而避免出现意外情况。当修改完S后,P1和P2会释放互斥锁mutex,并将信号量empty分配给进程P3。

进程P3首先会判断S是否为空,如果为空,则进入等待状态,直到进程P1或P2完成对S的修改,并将信号量empty分配给它。P3获得信号量empty后,输出S的值,然后释放信号量empty。

由于使用了信号量来实现同步,所以每个进程都会按照指定的顺序执行。进程执行的顺序对于最终的结果并没有影响,在修改S的过程中,一次只有一个进程可以对它进行修改。当一个进程修改了S后,它会立即将修改结果通知给其他进程,让它们也来修改。因此,进程P3总是能够得到正确的S的值。