有5个哲学家围着一张圆桌子,在每人的左右都有一根筷子,只有凑够两根筷子才可以吃饭,哲学家只有思考和吃饭两个动作,模拟这个过程,探究死锁的产生。
如果每个哲学家开始都是先拿起左边的筷子,等待着右边的人放下另外一根筷子,所有的哲学家都拿着一根筷子,所有的哲学家都在等筷子,这样就进入死锁的状态。
看一下代码实现:
哲学家类:

class Philosopher extends ReentrantLock implements Runnable{
    private String name;
    private volatile Chopstick leftChopstick;
    private volatile Chopstick rightChopstick;

    public Philosopher(String name, Chopstick leftChopstick, Chopstick rightChopstick) {
        this.name = name;
        this.leftChopstick = leftChopstick;
        this.rightChopstick = rightChopstick;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Chopstick getLeftChopstick() {
        return leftChopstick;
    }

    public void setLeftChopstick(Chopstick leftChopstick) {
        this.leftChopstick = leftChopstick;
    }

    public Chopstick getRightChopstick() {
        return rightChopstick;
    }

    public void setRightChopstick(Chopstick rightChopstick) {
        this.rightChopstick = rightChopstick;
    }

    public void think() {
        System.out.println("哲学家:"+name+" 正在思考");
        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void eat() {
        while (true) {
            if(!leftChopstick.isHeld()) {
                System.out.println("哲学家: "+name+"拿起了左边筷子:"+leftChopstick.getId());
                leftChopstick.setHeld(true);
                try {
                    Thread.sleep(20);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //System.out.println(leftChopstick.getId()+" "+leftChopstick.isHeld());
                break;
            } else {
                think();
            }
        }
        while (true) {
            if(!rightChopstick.isHeld()) {
                System.out.println("哲学家: "+name+"拿起了右边筷子:"+rightChopstick.getId());
                rightChopstick.setHeld(true);
                try {
                    Thread.sleep(20);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //System.out.println(rightChopstick.getId()+" "+rightChopstick.isHeld());
                break;

            } else {
                think();
            }
        }
        System.out.println("哲学家:" + name + "开始吃饭");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("哲学家: "+ name + "吃完");
        leftChopstick.setHeld(false);
        rightChopstick.setHeld(false);
    }

    @Override
    public void run() {
        eat();
    }
}

筷子类:

class Chopstick {
    private int id;
    AtomicBoolean isHeld;

    public Chopstick(int id, boolean isHeld) {
        this.id = id;
        this.isHeld = new AtomicBoolean(isHeld);
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public boolean isHeld() {
        return isHeld.get();
    }

    public void setHeld(boolean held) {
        isHeld.getAndSet(held);
    }
}

测试类:

public class PhilosopherEatTest {
    public static void main(String[] args) {
        Chopstick[] chopsticks = new Chopstick[5];
        for (int i = 0; i < 5; i++) {
            chopsticks[i] = new Chopstick(i,false);
        }
        Philosopher[] philosophers = new Philosopher[5];
        for (int i = 0; i < 5; i++) {
            philosophers[i] = new Philosopher(" "+i,chopsticks[i],chopsticks[(i+1)%5]);
        }
        for (int i = 0; i < 5; i++) {
            new Thread(philosophers[i]).start();
        }
    }
}

死锁:哲学家就餐问题
我的实现思路就是每个哲学家线程默认先去尝试拿左边的筷子,拿筷子是需要时间的,这个时候所有的线程都拿起了左边的筷子,而右边的筷子都被右边的哲学家拿起,这样就出现了僵持状态,出现了死锁。
这个就是模拟过程。

相关文章: