MST
星途 面试题库

面试题:并发与同步之信号量基础应用

假设有一个生产者 - 消费者模型,生产者生产数据并放入缓冲区,消费者从缓冲区取出数据。请使用信号量来实现这个模型,简要描述信号量的设计思路及对应的伪代码实现。
39.9万 热度难度
操作系统并发与同步

知识考点

AI 面试

面试题答案

一键面试

信号量设计思路

  1. 互斥信号量:用于保护共享缓冲区,确保同一时间只有一个线程能访问缓冲区,防止数据竞争。
  2. 满信号量:表示缓冲区中有多少个数据可供消费,初始值为0。
  3. 空信号量:表示缓冲区中有多少个空位可用于生产数据,初始值为缓冲区的大小。

伪代码实现

// 定义缓冲区大小
const int bufferSize = 10;
// 缓冲区
int buffer[bufferSize];
// 缓冲区索引
int in = 0;
int out = 0;

// 互斥信号量,初始值为1
Semaphore mutex(1); 
// 满信号量,初始值为0
Semaphore full(0); 
// 空信号量,初始值为缓冲区大小
Semaphore empty(bufferSize); 

// 生产者线程
void Producer() {
    while (true) {
        // 生产数据
        int data = ProduceData(); 
        // 获取一个空位置
        empty.Wait(); 
        // 进入临界区
        mutex.Wait(); 
        // 将数据放入缓冲区
        buffer[in] = data; 
        in = (in + 1) % bufferSize; 
        // 离开临界区
        mutex.Signal(); 
        // 通知缓冲区有新数据
        full.Signal(); 
    }
}

// 消费者线程
void Consumer() {
    while (true) {
        // 获取一个数据
        full.Wait(); 
        // 进入临界区
        mutex.Wait(); 
        // 从缓冲区取出数据
        int data = buffer[out]; 
        out = (out + 1) % bufferSize; 
        // 离开临界区
        mutex.Signal(); 
        // 通知缓冲区有一个空位
        empty.Signal(); 
        // 消费数据
        ConsumeData(data); 
    }
}

在上述伪代码中,ProduceData函数模拟生产数据,ConsumeData函数模拟消费数据。Semaphore类的Wait方法用于获取信号量,如果信号量值为0则阻塞,Signal方法用于释放信号量,将信号量值加1。通过这三个信号量的协同工作,实现了生产者 - 消费者模型。