MST

星途 面试题库

面试题:进程管理:进程程序段与数据段在进程同步中的协同作用

在一个多进程的系统中,进程间需要通过同步机制来保证程序段和数据段的正确协同。请阐述常用的进程同步方法(如信号量、互斥锁)是如何协调进程程序段对共享数据段的访问的,并举一个简单的生产者 - 消费者模型的例子说明。
23.8万 热度难度
操作系统进程管理

知识考点

AI 面试

面试题答案

一键面试

常用进程同步方法对共享数据段访问的协调

  1. 信号量(Semaphore)
    • 信号量是一个整型变量,它通过一个计数器来控制对共享资源的访问。
    • 当进程想要访问共享数据段时,它首先尝试获取信号量(将计数器减1)。如果计数器的值大于0,获取成功,进程可以访问共享数据;如果计数器的值为0,进程会被阻塞,直到其他进程释放信号量(将计数器加1)。
    • 例如,假设有一个共享缓冲区,信号量初始值设为缓冲区的容量。生产者进程每次向缓冲区写入数据前获取信号量,如果信号量计数器大于0,意味着缓冲区有空间,生产者可以写入,然后释放信号量;消费者进程每次从缓冲区读取数据前也获取信号量,读取后释放信号量。这样就保证了对共享缓冲区这一共享数据段的有序访问。
  2. 互斥锁(Mutex)
    • 互斥锁本质上是一种特殊的二元信号量(值为0或1)。
    • 当进程想要访问共享数据段时,它尝试获取互斥锁。如果互斥锁的值为1(表示未被占用),获取成功,进程可以访问共享数据,并将互斥锁的值设为0(表示已被占用);当进程访问完共享数据后,释放互斥锁,将其值设为1。
    • 若互斥锁的值为0(已被其他进程占用),当前进程会被阻塞,直到持有互斥锁的进程释放它。这就确保了在同一时刻只有一个进程能够访问共享数据段,避免了数据竞争。

生产者 - 消费者模型示例

  1. 使用Python和多进程模块以及信号量实现
import multiprocessing
import time


# 缓冲区大小
BUFFER_SIZE = 5
# 信号量,初始值为缓冲区大小
empty = multiprocessing.Semaphore(BUFFER_SIZE)
# 信号量,初始值为0
full = multiprocessing.Semaphore(0)
# 互斥锁
mutex = multiprocessing.Lock()
# 共享缓冲区
buffer = multiprocessing.Array('i', [0] * BUFFER_SIZE)
in_index = 0
out_index = 0


def producer(id):
    global in_index
    while True:
        empty.acquire()  # 获取空缓冲区信号量
        mutex.acquire()  # 加锁
        item = id * 10 + in_index
        buffer[in_index] = item
        print(f"Producer {id} produced {item}")
        in_index = (in_index + 1) % BUFFER_SIZE
        mutex.release()  # 解锁
        full.release()  # 释放满缓冲区信号量
        time.sleep(1)


def consumer(id):
    global out_index
    while True:
        full.acquire()  # 获取满缓冲区信号量
        mutex.acquire()  # 加锁
        item = buffer[out_index]
        print(f"Consumer {id} consumed {item}")
        out_index = (out_index + 1) % BUFFER_SIZE
        mutex.release()  # 解锁
        empty.release()  # 释放空缓冲区信号量
        time.sleep(1)


if __name__ == '__main__':
    producer1 = multiprocessing.Process(target=producer, args=(1,))
    consumer1 = multiprocessing.Process(target=consumer, args=(1,))
    producer1.start()
    consumer1.start()
    producer1.join()
    consumer1.join()


  1. 代码解释
    • empty信号量控制缓冲区的空闲空间,初始值为BUFFER_SIZE
    • full信号量控制缓冲区中的数据,初始值为0。
    • mutex互斥锁保证对共享缓冲区buffer的互斥访问。
    • producer函数模拟生产者,每次生产一个数据前先获取empty信号量,获取成功后加锁,将数据放入缓冲区,解锁并释放full信号量。
    • consumer函数模拟消费者,每次消费数据前先获取full信号量,获取成功后加锁,从缓冲区取出数据,解锁并释放empty信号量。