题目

5 个沉默寡言的哲学家围坐在圆桌前,每人面前一盘意面。叉子放在哲学家之间的桌面上。(5 个哲学家,5 根叉子)
每个哲学家想要吃面得拿起两个叉子。哲学家要么吃面要么思考。
哲学家编号:0-4
图片说明

思路

这是操作系统里的题目
死锁四个条件:互斥,请求并持有,不可剥夺,循环等待
一般设计程序都是破坏循环等待条件,还有就是超时kill破坏了请求并持有以及让出资源

  • 1)同一时间只允许一个人进餐,想要进餐得获得互斥锁
  • 2)对上种思路的优化:同一时间允许4个人进餐,Seamphore(4)
  • 3)编号奇数为先左手拿叉子,偶数先右手拿叉子
  • 4)与思路3类似:除了编号4先右手,其他人全是先拿左手,也就是每个哲学家先拿编号小的叉子

代码

上述四种思路都可以用信号量完成

至多允许4个人同时想进餐

class DiningPhilosophers {
    Semaphore semaphore = new Semaphore(4);
    Semaphore[] seaps;

    public DiningPhilosophers(){
        seaps = new Semaphore[5];
        for(int i = 0; i < 5; i++){
            seaps[i] = new Semaphore(1);
        }
    }
    public void wantsToEat(int philosopher,
            Runnable pickLeftFork,  //左手拿叉子
            Runnable pickRightFork,
            Runnable eat,  //进餐
            Runnable putLeftFork,//左手释放叉子
            Runnable putRightFork) throws InterruptedException{
                //先获得进餐权限
        semaphore.acquire();
                //获得叉子
        seaps[philosopher].acquire();
        seaps[(philosopher + 1) % 5].acquire();
        pickLeftFork.run();
        pickRightFork.run();
        eat.run();
        putLeftFork.run();
        putRightFork.run();

seaps[(philosopher + 1) % 5].release();
        seaps[philosopher].release();
        semaphore.release();//注意释放资源顺序与获得顺序相反
    }

固定拿叉子顺序

package MultiProcessing;

import java.util.concurrent.Semaphore;

class DiningPhilosophers {
    Semaphore[] seaps;

    public DiningPhilosophers(){
        seaps = new Semaphore[5];
        for(int i = 0; i < 5; i++){
            seaps[i] = new Semaphore(1);
        }
    }

    public void wantsToEat(int philosopher,
            Runnable pickLeftFork,
            Runnable pickRightFork,
            Runnable eat,
            Runnable putLeftFork,
            Runnable putRightFork) throws InterruptedException{
        int first;
        int second;
        if(philosopher == 4){
            first = (philosopher + 1) % 5;//4号哲学家先拿0号叉子再拿4号叉子
            second = philosopher;
        }else{
            first = philosopher;
            second = (philosopher + 1) % 5;
        }
        seaps[first].acquire();
        seaps[second].acquire();
        pickLeftFork.run();
        pickRightFork.run();
        eat.run();
        putLeftFork.run();
        putRightFork.run();
        seaps[second].release();
        seaps[first].release();
    }
}