高分悬赏:Java语言模拟哲学家用餐,要求代码自行完成,不能拷贝网上的

假设有 5 个哲学家,他们的生活只是思考和吃饭。这些哲学家共用一个圆桌,每位都有一把椅子。在桌子中央有一碗米饭,在桌子上放着 5 根筷子。

当一位哲学家思考时,他与其他同事不交流。时而,他会感到饥饿,并试图拿起与他相近的两根筷子(筷子在他和他的左或右邻居之间)。一个哲学家一次只能拿起一根筷子。显然,他不能从其他哲学家手里拿走筷子。当一个饥饿的哲学家同时拥有两根筷子时,他就能吃。在吃完后,他会放下两根筷子,并开始思考。

哲学家就餐问题是一个经典的同步问题,这不是因为其本身的实际重要性,也不是因为计算机科学家不喜欢哲学家,而是因为它是大量并发控制问题的一个例子。这个代表型的例子满足:在多个进程之间分配多个资源,而且不会出现死锁和饥饿。

具体的做法 https://blog.csdn.net/maikelsong/article/details/50800583


class DiningPhilosophers {
    //一个互斥信号量用于临界资源的互斥访问
    private Semaphore mutex;
    //5个同步信号量用于哲学家之间的同步访问
    private Semaphore[] sema;
    public DiningPhilosophers() {
        mutex = new Semaphore(1);
        sema = new Semaphore[] {
            new Semaphore(1),
            new Semaphore(1),
            new Semaphore(1),
            new Semaphore(1),
            new Semaphore(1)
        };
    }

    // call the run() method of any runnable to execute its code
    public void wantsToEat(int philosopher,
                           Runnable pickLeftFork,
                           Runnable pickRightFork,
                           Runnable eat,
                           Runnable putLeftFork,
                           Runnable putRightFork) throws InterruptedException {
        //一个哲学家如果要拿起叉子就同时拿两个,因此这里是一个原子操作,需要用mutex信号量包起来,表示互斥
        mutex.acquire();
        //尝试获取左手边的叉子
        sema[philosopher].acquire();
        //尝试获取右手边的叉子
        sema[(philosopher+1) % 5].acquire();

        pickLeftFork.run();
        pickRightFork.run();
        //我认为这句话应该放在这里。
        // mutex.release();

        //拿到叉子开始吃饭
        eat.run();

        //吃完饭放下叉子
        putLeftFork.run();
        sema[philosopher].release();
        putRightFork.run();
        sema[(philosopher+1) % 5].release();
        mutex.release();
    }
}