-2

我正在尝试解决哲学家就餐问题问题: https ://en.wikipedia.org/wiki/Dining_philosophers_problem ),我找到了以下代码的解决方案。解决方案使用信号量和一个互斥体。我自己实现了忙等待简单信号量,因为 C++ 不提供信号量。我不明白互斥锁锁定take_forksput_forks功能的目的是什么。

我试图找到我的问题的答案,但我找不到。所以我在stackoverflow中问。

我的问题是:

  1. 互斥锁锁定take_forksput_forks功能的目的是什么?(什么会导致竞争条件发生?)
  2. 这个解决方案的名称是什么?这是仲裁解决方案吗?

这是我的代码

#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起作用,因为这是我发现的竞争条件的唯一原因。

任何答案和建议表示赞赏!谢谢!

4

1 回答 1

0

我找到了我的问题的答案。

该解决方案由 A. Tanenbaum 介绍,是称为仲裁的几种解决方案之一。通过这种方法,通过引入仲裁员(例如服务员),可以保证哲学家只能拿起或不拿起叉子。为了拿起叉子,哲学家必须征得服务员的许可。服务员一次只允许一位哲学家,直到他拿起他的两把叉子。服务员可以实现为互斥体。因此,检查和更新数组的操作是原子的,并且保证了对 fork 的独占访问。(这就是互斥锁的目的)


几个参考

于 2019-06-13T22:53:44.530 回答