用记录型信号量实现不会死锁的哲学家就餐问题
使用记录型信号量(std::binary_semaphore
)来确保不会发生死锁。这个示例代码假设有5位哲学家,每位哲学家有一个左侧筷子和一个右侧筷子:
#include <iostream>
#include <vector>
#include <thread>
#include <semaphore>
const int num_philosophers = 5;
std::vector<std::jthread> philosophers;
std::vector<std::binary_semaphore> forks(num_philosophers);
void philosopher(int id) {
while (true) {
// 哲学家思考
std::cout << "哲学家 " << id << " 思考" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(200));
// 哲学家饿了,尝试拿起筷子
std::cout << "哲学家 " << id << " 饿了,尝试拿起筷子" << std::endl;
// 尝试获取左侧筷子
forks[id].acquire();
std::cout << "哲学家 " << id << " 拿到左侧筷子" << std::endl;
// 尝试获取右侧筷子
forks[(id + 1) % num_philosophers].acquire();
std::cout << "哲学家 " << id << " 拿到右侧筷子,开始就餐" << std::endl;
// 哲学家就餐
std::this_thread::sleep_for(std::chrono::milliseconds(300));
std::cout << "哲学家 " << id << " 就餐完毕,放下筷子" << std::endl;
// 放下左侧筷子
forks[id].release();
// 放下右侧筷子
forks[(id + 1) % num_philosophers].release();
}
}
int main() {
// 创建哲学家线程
for (int i = 0; i < num_philosophers; ++i) {
philosophers.emplace_back(philosopher, i);
}
// 让程序一直运行
for (int i = 0; i < num_philosophers; ++i) {
philosophers[i].join();
}
return 0;
}
这个C++示例中使用了std::binary_semaphore
来表示筷子,哲学家在思考后会尝试获取左侧筷子和右侧筷子,然后就餐完成后释放它们。记录型信号量确保每位哲学家都能同时获取两根筷子,从而避免死锁。