面试题答案
一键面试信号量设计思路
- 互斥信号量:用于保护共享缓冲区,确保同一时间只有一个线程能访问缓冲区,防止数据竞争。
- 满信号量:表示缓冲区中有多少个数据可供消费,初始值为0。
- 空信号量:表示缓冲区中有多少个空位可用于生产数据,初始值为缓冲区的大小。
伪代码实现
// 定义缓冲区大小
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。通过这三个信号量的协同工作,实现了生产者 - 消费者模型。