操作系统笔记:(十续) 哲学家就餐问题(java 实现)

关于哲学家就餐问题的完整解答可参见:

Dining philosophers problem

里面列出了3种解法:

  • 服务生解法
  • 资源分级解法
  • Chandy/Misra solution

这里会陆续给出3种解决方案

服务生解法

一个简单的解法是引入一个餐厅服务生,哲学家必须经过他的允许才能拿起餐叉。因为服务生知道哪只餐叉正在使用,所以他能够作出判断避免死锁。
为了演示这种解法,假设哲学家依次标号为A至E。如果A和C在吃东西,则有四只餐叉在使用中。B坐在A和C之间,所以两只餐叉都无法使用,而D和E之间有一只空余的餐叉。假设这时D想要吃东西。如果他拿起了第五只餐叉,就有可能发生死锁。相反,如果他征求服务生同意,服务生会让他等待。这样,我们就能保证下次当两把餐叉空余出来时,一定有一位哲学家可以成功的得到一对餐叉,从而避免了死锁

我感觉就是,引入仲裁,当且仅当可以吃的时候他才拿起筷子,否则等待

package tmp;

public class Main {

    public static void main(String[] args) {
        Fork fork = new Fork();
        for(int i=0 ; i<5 ; ++i)
            (new Philosopher(i, fork)).start();
    }
}

class Fork{
    private boolean[] used = new boolean[]{false,false,false,false,false};

    public synchronized void take(int i) throws InterruptedException{
        while (used[i] || used[(i+1)%5]) {
            System.out.printf("I'm philosopher %d, wait for used[%d] =%d used[%d]=%d\n", i,i,used[i]?1:0,(i+1)%5,used[(i+1)%5]?1:0);
            wait();
        }
        used[i] = true;
        used[(i+1)%5] = true;
    }
    public synchronized void put(int i){
        used[i] = false;
        used[(i+1)%5] = false;
        notifyAll();
    }
}



class Philosopher extends Thread{
    private int id;
    private Fork fork;

    public Philosopher(int id, Fork fork) {
        super();
        this.id = id;
        this.fork = fork;
    }

    private void eat() throws InterruptedException {
        int time =(int) (Math.max(0.5, Math.random()) * 2000);//至少1秒
        System.out.printf("philosopher %d is eating for %d mils\n",id,time);
        this.sleep(time);
    }
    private void think() throws InterruptedException {
        int time =(int) (Math.max(0.5, Math.random()) * 5000);//至少1秒
        System.out.printf("philosopher %d is eating for %d mils\n",id,time);
        this.sleep(time);
    }
    public void run() {
        while (true) {
            try {
                think();
                fork.take(id);
                eat();
                fork.put(id);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

显然不会引起死锁,因为不会发生循环等待,也即没有哲学家会在饥饿的同时拿起一只筷子

你可能感兴趣的:(system&software,engineer)