https://leetcode-cn.com/problems/the-dining-philosophers/
求解思路题目没有提供C语言解决方案,只能采用C++,C++有一套自己封装了POSIX的线程库,然而我并不会用,只能还是调用底层的sem_t互斥量及其相关 *** 作集来实现线程同步(又逮到一个C with class)
对于哲学家进餐问题,一共有三种方式避免死锁:
- 保证每个哲学家拿叉子互斥,即对哲学家拿起左右两只叉子这个过程上锁保护
- 令奇数号哲学家先拿左手边的叉子,偶数号的哲学家先拿右手边的叉子
- 至多允许4名哲学家同时吃饭
死锁避免方式1:利用mutex保证哲学家同时拿左右两只叉子
#includeclass DiningPhilosophers { public: DiningPhilosophers() { for (int i = 0; i < 5; ++i) { sem_init(&forks[i], 0, 1); } sem_init(&mutex, 0, 1); } ~DiningPhilosophers() { for (int i = 0; i < 5; ++i) { sem_destroy(&forks[i]); } sem_destroy(&mutex); } void wantsToEat(int philosopher, function pickLeftFork, function pickRightFork, function eat, function putLeftFork, function putRightFork) { int leftFork = philosopher; int rightFork = (philosopher + 1) % 5; sem_wait(&mutex); sem_wait(&forks[leftFork]); sem_wait(&forks[rightFork]); sem_post(&mutex); pickLeftFork(); pickRightFork(); eat(); putLeftFork(); putRightFork(); sem_post(&forks[leftFork]); sem_post(&forks[rightFork]); } private: sem_t forks[5]; sem_t mutex; }
死锁避免方式2:奇数号哲学家先拿左手边的叉子,偶数号的哲学家先拿右手边的叉子
#includeclass DiningPhilosophers { public: DiningPhilosophers() { for (int i = 0; i < 5; ++i) { sem_init(&forks[i], 0, 1); } } ~DiningPhilosophers() { for (int i = 0; i < 5; ++i) { sem_destroy(&forks[i]); } } void wantsToEat(int philosopher, function pickLeftFork, function pickRightFork, function eat, function putLeftFork, function putRightFork) { int leftFork = philosopher; int rightFork = (philosopher + 1) % 5; if ((philosopher & 1) == 1) { sem_wait(&forks[leftFork]); sem_wait(&forks[rightFork]); pickLeftFork(); pickRightFork(); } else { sem_wait(&forks[rightFork]); sem_wait(&forks[leftFork]); pickRightFork(); pickLeftFork(); } eat(); putLeftFork(); putRightFork(); sem_post(&forks[leftFork]); sem_post(&forks[rightFork]); } private: sem_t forks[5]; };
死锁避免方式3:最多允许4个哲学家同时进餐
#include收获和疑惑class DiningPhilosophers { public: DiningPhilosophers() { for (int i = 0; i < 5; ++i) { sem_init(&forks[i], 0, 1); } sem_init(&nums, 0, 4); } ~DiningPhilosophers() { for (int i = 0; i < 5; ++i) { sem_destroy(&forks[i]); } sem_destroy(&nums); } void wantsToEat(int philosopher, function pickLeftFork, function pickRightFork, function eat, function putLeftFork, function putRightFork) { int leftFork = philosopher; int rightFork = (philosopher + 1) % 5; sem_wait(&nums); sem_wait(&forks[leftFork]); sem_wait(&forks[rightFork]); pickLeftFork(); pickRightFork(); eat(); putLeftFork(); putRightFork(); sem_post(&forks[leftFork]); sem_post(&forks[rightFork]); sem_post(&nums); } private: sem_t forks[5]; sem_t nums; };
C++提供了比函数指针更高级的函数作为参数传递的方式:借助function关键字,有时间深入学习。
有时间学习一下C++封装好的线程库。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)