面试题答案
一键面试信号量原理
信号量(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);
}
}
在上述伪代码中:
empty
信号量用于表示缓冲区中的空槽位数量,初始值为bufferSize
。full
信号量用于表示缓冲区中的已占用槽位数量,初始值为 0。mutex
是一个互斥锁,用于保护对共享缓冲区的访问,确保同一时间只有一个线程可以访问缓冲区。- 生产者线程先获取
empty
信号量(如果没有空槽位则等待),然后进入临界区,将数据放入缓冲区,离开临界区后释放full
信号量,表示缓冲区有新的数据。 - 消费者线程先获取
full
信号量(如果没有已占用槽位则等待),然后进入临界区,从缓冲区取出数据,离开临界区后释放empty
信号量,表示缓冲区有了空槽位。