
思路:
参考题解:https://leetcode-cn.com/problems/the-dining-philosophers/solution/zhe-xue-jia-jiu-can-wen-ti-by-mike-meng/
解法1:控制同时拿筷子的哲学家人数(不多于4个)
class Semaphore {
public:Semaphore(int count = 0): count_(count){}void Set(int count) {count_ = count;}void Signal() {unique_lock<mutex>lock(mutex_);++count_;cv_.notify_one();}void Wait() {unique_lock<mutex>lock(mutex_);while(count_ <= 0) {cv_.wait(lock);}--count_;}
private:mutex mutex_;condition_variable cv_;int count_;
};
class DiningPhilosophers {
public:DiningPhilosophers() {guid.Set(4);}void wantsToEat(int philosopher,function<void()> pickLeftFork,function<void()> pickRightFork,function<void()> eat,function<void()> putLeftFork,function<void()> putRightFork) {int l = philosopher;int r = (philosopher + 1) % 5;guid.Wait();lock[l].lock();lock[r].lock();pickLeftFork();pickRightFork();eat();putRightFork();putLeftFork();lock[r].unlock();lock[l].unlock();guid.Signal();}
private:mutex lock[5];Semaphore guid;
};
解法2:使用互斥量,使得哲学家一次只能拿上左右筷子
class DiningPhilosophers {
public:DiningPhilosophers() {}void wantsToEat(int philosopher,function<void()> pickLeftFork,function<void()> pickRightFork,function<void()> eat,function<void()> putLeftFork,function<void()> putRightFork) {int l = philosopher;int r = (philosopher + 1) % 5;guid.lock();lock[l].lock();lock[r].lock();pickLeftFork();pickRightFork();guid.unlock();eat();putRightFork();putLeftFork();lock[r].unlock();lock[l].unlock();}
private:mutex lock[5];mutex guid;
};
解法3:限定就餐,奇数位优先拿左边筷子,偶数位优先拿右边筷子
class DiningPhilosophers {
public:DiningPhilosophers() {}void wantsToEat(int philosopher,function<void()> pickLeftFork,function<void()> pickRightFork,function<void()> eat,function<void()> putLeftFork,function<void()> putRightFork) {int l = philosopher;int r = (philosopher + 1) % 5;if(philosopher % 2 == 0) {lock[r].lock();lock[l].lock();pickRightFork();pickLeftFork();eat();putLeftFork();putRightFork();lock[l].unlock();lock[r].unlock();} else {lock[l].lock();lock[r].lock();pickLeftFork();pickRightFork();eat();putRightFork();putLeftFork();lock[r].unlock();lock[l].unlock();}}
private:mutex lock[5];
};