这个哲学家就餐问题 (dpp) 的解决方案是如何工作的?互斥量和信号量
How is this solution for dining philosophers problem (dpp) working? Mutex and semaphores
我正在尝试解决哲学家用餐问题(问题:https://en.wikipedia.org/wiki/Dining_philosophers_problem) 我找到了下面代码的解决方案。解决方案使用信号量和一个互斥量。我自己实现了忙等待简单信号量,因为 C++ 不提供信号量。我不明白 take_forks
和 put_forks
函数中互斥锁的目的是什么。
我试图找到问题的答案,但找不到。所以我在 Whosebug 中询问。
我的问题是:
take_forks
和 put_forks
函数中互斥锁的目的是什么? (什么会导致竞争条件发生?)
- 这个解决方案的名称是什么?这是仲裁解决方案吗?
这是我的代码
#include <mutex>
#include <thread>
#define N 5
#define THINKING 0
#define HUNGRY 1
#define EATING 2
typedef int sem_t;
void sem_up(sem_t* semaphore) {
(*semaphore)++;
}
void sem_down(sem_t* semaphore) {
while (*semaphore == 0) {}
(*semaphore)--;
}
std::mutex mutualExclusion;
char philosopherState[N] = {THINKING};
sem_t philosopherSemaphore[N] = { 0 };
void test(short i) {
if (philosopherState[i] == HUNGRY && philosopherState[(i + 1) % N] != EATING && philosopherState[(i + N - 1) % N] != EATING) {
philosopherState[i] = EATING;
sem_up(&philosopherSemaphore[i]);
}
}
void think(short p) {
//some code
}
void eat() {
//some code
}
void take_forks(short i) {
::mutualExclusion.lock();
philosopherState[i] = HUNGRY;
test(i);
::mutualExclusion.unlock();
sem_down(&philosopherSemaphore[i]);
}
void put_forks(short i) {
::mutualExclusion.lock();
philosopherState[i] = THINKING;
test((i + 1) % N);
test((i + N - 1) % N);
::mutualExclusion.unlock();
}
void philosopher(short i) {
while (1) {
think();
take_forks(i);
eat();
put_forks(i);
}
}
我预计互斥锁定必须在 test
函数中,因为这是我发现的竞争条件的唯一原因。
如有任何答案和建议,我们将不胜感激!谢谢!
我找到了问题的答案。
此解决方案由 A. Tanenbaum 介绍,是称为仲裁的几种解决方案之一。通过这种方法,可以保证哲学家只能通过引入 [来选择 叉子或 none =21=]仲裁者,例如服务员。为了拿起叉子,哲学家必须征得服务员的许可。服务员一次只允许一位哲学家,直到他拿起他的两把叉子。服务员可以实现为互斥体。因此,检查和更新数组的操作是原子的,并且保证了对分叉的独占访问。 (这就是互斥量的目的)
几个参考文献
我正在尝试解决哲学家用餐问题(问题:https://en.wikipedia.org/wiki/Dining_philosophers_problem) 我找到了下面代码的解决方案。解决方案使用信号量和一个互斥量。我自己实现了忙等待简单信号量,因为 C++ 不提供信号量。我不明白 take_forks
和 put_forks
函数中互斥锁的目的是什么。
我试图找到问题的答案,但找不到。所以我在 Whosebug 中询问。
我的问题是:
take_forks
和put_forks
函数中互斥锁的目的是什么? (什么会导致竞争条件发生?)- 这个解决方案的名称是什么?这是仲裁解决方案吗?
这是我的代码
#include <mutex>
#include <thread>
#define N 5
#define THINKING 0
#define HUNGRY 1
#define EATING 2
typedef int sem_t;
void sem_up(sem_t* semaphore) {
(*semaphore)++;
}
void sem_down(sem_t* semaphore) {
while (*semaphore == 0) {}
(*semaphore)--;
}
std::mutex mutualExclusion;
char philosopherState[N] = {THINKING};
sem_t philosopherSemaphore[N] = { 0 };
void test(short i) {
if (philosopherState[i] == HUNGRY && philosopherState[(i + 1) % N] != EATING && philosopherState[(i + N - 1) % N] != EATING) {
philosopherState[i] = EATING;
sem_up(&philosopherSemaphore[i]);
}
}
void think(short p) {
//some code
}
void eat() {
//some code
}
void take_forks(short i) {
::mutualExclusion.lock();
philosopherState[i] = HUNGRY;
test(i);
::mutualExclusion.unlock();
sem_down(&philosopherSemaphore[i]);
}
void put_forks(short i) {
::mutualExclusion.lock();
philosopherState[i] = THINKING;
test((i + 1) % N);
test((i + N - 1) % N);
::mutualExclusion.unlock();
}
void philosopher(short i) {
while (1) {
think();
take_forks(i);
eat();
put_forks(i);
}
}
我预计互斥锁定必须在 test
函数中,因为这是我发现的竞争条件的唯一原因。
如有任何答案和建议,我们将不胜感激!谢谢!
我找到了问题的答案。
此解决方案由 A. Tanenbaum 介绍,是称为仲裁的几种解决方案之一。通过这种方法,可以保证哲学家只能通过引入 [来选择 叉子或 none =21=]仲裁者,例如服务员。为了拿起叉子,哲学家必须征得服务员的许可。服务员一次只允许一位哲学家,直到他拿起他的两把叉子。服务员可以实现为互斥体。因此,检查和更新数组的操作是原子的,并且保证了对分叉的独占访问。 (这就是互斥量的目的)