MST

星途 面试题库

面试题:并发与同步之生产者消费者问题中等难度

在生产者 - 消费者模型中,假设使用信号量来实现同步。请简述信号量的原理,并给出使用信号量解决生产者消费者问题的伪代码实现,需考虑缓冲区满和缓冲区空的情况。
45.5万 热度难度
操作系统并发与同步

知识考点

AI 面试

面试题答案

一键面试

信号量原理

信号量(Semaphore)是一个整型变量,通过一个计数器来控制对共享资源的访问。当计数器大于0时,表示有可用资源,线程可以获取信号量(将计数器减1)来访问资源;当计数器为0时,表示资源已被占用,线程需要等待,直到其他线程释放信号量(将计数器加1)。

伪代码实现

// 定义缓冲区大小
const int bufferSize = 5;
// 缓冲区
int buffer[bufferSize];
// 缓冲区当前位置
int in = 0;
int out = 0;

// 信号量:表示缓冲区中可用的槽位
Semaphore empty(bufferSize);
// 信号量:表示缓冲区中已占用的槽位
Semaphore full(0);
// 互斥锁,用于保护对缓冲区的访问
Mutex mutex;

// 生产者线程函数
void producer() {
    while (true) {
        // 生成数据
        int item = produceItem();
        // 获取一个空槽位
        empty.wait();
        // 进入临界区
        mutex.lock();
        // 将数据放入缓冲区
        buffer[in] = item;
        in = (in + 1) % bufferSize;
        // 离开临界区
        mutex.unlock();
        // 释放一个已占用的槽位
        full.signal();
    }
}

// 消费者线程函数
void consumer() {
    while (true) {
        // 获取一个已占用的槽位
        full.wait();
        // 进入临界区
        mutex.lock();
        // 从缓冲区取出数据
        int item = buffer[out];
        out = (out + 1) % bufferSize;
        // 离开临界区
        mutex.unlock();
        // 释放一个空槽位
        empty.signal();
        // 消费数据
        consumeItem(item);
    }
}

在上述伪代码中:

  1. empty 信号量用于表示缓冲区中的空槽位数量,初始值为 bufferSize
  2. full 信号量用于表示缓冲区中的已占用槽位数量,初始值为 0。
  3. mutex 是一个互斥锁,用于保护对共享缓冲区的访问,确保同一时间只有一个线程可以访问缓冲区。
  4. 生产者线程先获取 empty 信号量(如果没有空槽位则等待),然后进入临界区,将数据放入缓冲区,离开临界区后释放 full 信号量,表示缓冲区有新的数据。
  5. 消费者线程先获取 full 信号量(如果没有已占用槽位则等待),然后进入临界区,从缓冲区取出数据,离开临界区后释放 empty 信号量,表示缓冲区有了空槽位。