用餐哲学家问题中的饥饿

时间:2018-09-02 19:09:21

标签: multithreading parallel-processing dining-philosopher starvation

我一直在寻找维基百科上餐饮哲学家问题的解决方案。 The resource hierarchy solution

我了解它是如何工作的,打破圆形结构如何防止死锁,但是解决方案如何防止饥饿?一个或几个线程不能继续前进,而几个线程却无法取得进展吗?

如果没有,什么阻止了这种情况的发生?

实现:

public class DinningphilMain {



    public static void main(String[] args) throws InterruptedException {


        int numPhil = 3;

        Philosopher[] phil = new Philosopher[numPhil];

        Fork[] forkArr=new Fork[numPhil];


        for (int i = 0; i < numPhil; i ++) {
            forkArr[i]= new Fork(i);
        }

        for (int i = 0; i < numPhil-1; i++) {
            phil[i]=new Philosopher(i, forkArr[i], forkArr[i+1]);
        }
        phil[numPhil-1]= new Philosopher(numPhil-1, forkArr[0], forkArr[numPhil-1]);

        for (Philosopher p : phil)
            new Thread(p).start();


    }
}

这是哲学家课

import java.util.Random;

public class Philosopher implements Runnable {

    int sleep = 1000;
    int id;
    int eatTime= 500;
    Random rand = new Random();
    Fork left;
    Fork right;


    public Philosopher(int id,  Fork left, Fork right) {
        this.id = id;
        this.left = left;
        this.right = right;

    }


    private void think() {
        System.out.println("Philosopher " + id + " is thinking");
        try {
            int thinkingTime = rand.nextInt(sleep);
            Thread.sleep(thinkingTime);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void getForks() {
        System.out.println("Philosopher " + id + " is picking up forks");
        try {
            left.get();
            right.get();
            System.out.println("Philosopher " + id + " has both forks");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    private void releaseForks() {
        System.out.println("Philosopher " + id + " is putting down forks");
        left.release();
        right.release();
    }

    private void eat()  {
        System.out.println("Philosopher " + id + " is eating");
        try {
            Thread.sleep(eatTime);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }



    @Override
    public void run() {
            while (true) {
                getForks();
                eat();
                releaseForks();
                think();
            }

    }
}

这是fork类

public class Fork {

    private int id;
    private Thread thread;

    public Fork(int id) {
        this.id = id;
        thread = null;
    }

    public int getId() {
        return id;
    }

    public synchronized void get() throws InterruptedException {
        if (thread != null) 
            this.wait();
        thread = Thread.currentThread();
    }

    public synchronized void release() {
        if (thread == Thread.currentThread())
            thread = null;
        this.notify();
    }

}

2 个答案:

答案 0 :(得分:2)

资源层次解决方案可以解决死锁,但不能解决饥饿问题。

为了防止饥饿,您要么需要:

  
      
  • 线程系统保证线程将不受阻塞   监视和条件变量的顺序与它们相同   被阻止。

  •   
  • 自己动手做。换句话说,您必须保证没有   哲学家可能会饿死。例如,假设您维护一个队列   哲学家。当哲学家饥饿时,他/她会被放在   队列的尾部。哲学家只有在头脑中才能吃东西   ,如果没有筷子。

  •   

这取自C560 Lecture notes -- Dining Philosophers

答案 1 :(得分:1)

简短的回答是,没有。餐饮哲学家问题用来讨论并发问题;它本身并不是解决任何问题的单一解决方案(因此为什么将其称为问题)。

餐饮哲学家本身的Wikipedia页面显示了一些实现。第一个显示了解决方案的不良实施将如何导致饥饿。

https://en.wikipedia.org/wiki/Dining_philosophers_problem