Java 《哲学家法典》中的饥饿

Java 《哲学家法典》中的饥饿,java,multithreading,concurrency,Java,Multithreading,Concurrency,下面是我对并发问题的实现。我只为两个线程工作,其余的线程都饱受饥饿之苦如果你能找到原因,我将不胜感激 以下是输出: Philosopher 2 is eating Philosopher 0 is eating Philosopher 2 is eating Philosopher 0 is eating Philosopher 2 is eating Philosopher 0 is eating Philosopher 2 is eating Philosopher 0 is eating

下面是我对并发问题的实现。我只为两个线程工作,其余的线程都饱受饥饿之苦如果你能找到原因,我将不胜感激

以下是输出:

Philosopher 2 is eating
Philosopher 0 is eating
Philosopher 2 is eating
Philosopher 0 is eating
Philosopher 2 is eating
Philosopher 0 is eating
Philosopher 2 is eating
Philosopher 0 is eating
Philosopher 2 is eating
Philosopher 2 is eating
Philosopher 0 is eating
Philosopher 2 is eating
Philosopher 0 is eating
代码如下:

public class PhilosophersDinner {

    public static void main(String[] args) {
        Chopstick2[] chopsticks = new Chopstick2[5];
        Philosopher [] philosophers = new Philosopher[5];

        for (int i = 0; i < 5; i++) {
            Chopstick2 stick = new Chopstick2();
            chopsticks[i] = stick;
        }

        for (int i = 0; i < 5; i++) {
            Philosopher philo = new Philosopher(chopsticks[i] , chopsticks[(i+1)%5], i+"");
            philosophers[i] = philo;
        }

        for (int i = 0; i < philosophers.length; i++) {
            new Thread(philosophers[i]).start();
        }
    }

}

class Philosopher implements Runnable {

    private final Chopstick2 left;
    private final Chopstick2 right;
    private final String id;

    public Philosopher(Chopstick2 l, Chopstick2 r, String id){
        this.left = l;
        this.right = r;
        this.id = id;
    }

    public void eat(){
        if (left.pickUp()) {
            if (right.pickUp()) {
                chew();
                putDown();
            } else left.putDown();
        }
    }


    public void run(){
        for (int i = 0; i < 10; i++) {
            eat();
        }
    }

    public void chew(){
        try {
            System.out.println("Philosopher "+id+" is eating");
            Thread.sleep(400);
        } catch (InterruptedException e) {
            e.printStackTrace();
            // release lock here?
        } 
    }

    public void putDown(){
        left.putDown();
        right.putDown();
    }

}

class Chopstick2 {
    private volatile boolean taken = false;

    public synchronized boolean pickUp(){
        if (!taken) { 
            taken = true;
            return true;
        }
        else return false;
    }

    public synchronized void putDown(){
        taken = false;
    }
}
公共类哲学{
公共静态void main(字符串[]args){
筷子2[]筷子=新筷子2[5];
哲学家[]哲学家=新哲学家[5];
对于(int i=0;i<5;i++){
筷子2棒=新筷子2();
筷子=棍子;
}
对于(int i=0;i<5;i++){
哲学家菲洛=新哲学家(筷子[i],筷子[i+1)%5],i+”);
哲学家们,菲罗;
}
for(int i=0;i<0.length;i++){
新线程(哲学家[i]).start();
}
}
}
类实现Runnable{
私人决赛结束,剩余2人;
私人最终许可证2项权利;
私有最终字符串id;
公共哲学家(Chopptick2L,Chopptick2R,字符串id){
这个左=l;
这个。右=r;
this.id=id;
}
公共图书馆{
if(left.pickUp()){
if(right.pickUp()){
咀嚼();
放下();
}否则我就走了;
}
}
公开募捐{
对于(int i=0;i<10;i++){
吃();
}
}
公众假期{
试一试{
System.out.println(“哲学家”+id+“正在吃”);
睡眠(400);
}捕捉(中断异常e){
e、 printStackTrace();
//在这里开锁?
} 
}
公屋空置{
左。放下();
对。放下();
}
}
第2类{
private=false;
公共同步布尔拾取(){
如果(!take){
假设为真;
返回true;
}
否则返回false;
}
公共同步无效放下(){
take=false;
}
}

问题在于,前两位获得筷子的哲学家花了半秒钟的时间吃饭,而在这段时间里,其他三位用餐者则试图吃饭,直到他们放弃并退出为止

一种解决办法是让所有的哲学家在规定的时间内进食,而不是尝试特定次数的进食

    for (long i = System.currentTimeMillis()+10000; i > System.currentTimeMillis(); ) {
        eat();
    }

我只是简单地看了一下代码,但这个问题的经典解决方案是至少有一个右撇子哲学家和至少一个左撇子,这将避免死锁。为了避免饥饿,你需要实现一个监视器(一个信号灯和一个队列相结合)。谢谢你指出了杰克,但是如果在拿走右边的筷子时松开左边的筷子,它怎么会死锁呢?应该是
。更好的是,用一个合适的变量名和
while
循环来替换它。