练习题1:哲学家吃饭问题

时间:2022-07-21 01:08:48

哲学家就餐问题是在计算机科学中的一个经典问题,用来演示在并行计算中多线程同步(Synchronization)时产生的问题。
有五个哲学家,他们共用一张圆桌,分别坐在五张椅子上。在圆桌上有五个碗和五支筷子,平时一个哲学家进行思考,饥饿时便试图取用其左、右最靠近他的筷子,只有在他拿到两支筷子时才能进餐。进餐完毕,放下筷子。

练习题1:哲学家吃饭问题

code:

两个对象:Chopsticks 空。

    public static class PhilosopherThread extends Thread {

        private Chopsticks left;

        private Chopsticks right;

        private int index;

        public PhilosopherThread(Chopsticks left, Chopsticks right, int index) {
            this.left = left;
            this.index = index;
            this.right = right;
        }

        @Override
        public void run() {
            synchronized (left) {
                try {
                    Thread.sleep(3000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(index + "等待获取筷子left进行吃饭");
                synchronized (right) {
                    System.out.println(index + "获取筷子RIGHT进行吃饭");
                }
            }

        }


    }

测试输出:

 public static void main(String[] args) {
        Chopsticks chopsticks1 = new Chopsticks();
        Chopsticks chopsticks2 = new Chopsticks();
        Chopsticks chopsticks3 = new Chopsticks();
        Chopsticks chopsticks4 = new Chopsticks();
        Chopsticks chopsticks5 = new Chopsticks();

        PhilosopherThread philosopherThread1 = new PhilosopherThread(chopsticks1, chopsticks2, 1);
        PhilosopherThread philosopherThread2 = new PhilosopherThread(chopsticks2, chopsticks3, 2);
        PhilosopherThread philosopherThread3 = new PhilosopherThread(chopsticks3, chopsticks4, 3);
        PhilosopherThread philosopherThread4 = new PhilosopherThread(chopsticks4, chopsticks5, 4);
        PhilosopherThread philosopherThread5 = new PhilosopherThread(chopsticks5, chopsticks1, 5);
        philosopherThread1.start();
        philosopherThread2.start();
        philosopherThread3.start();
        philosopherThread4.start();
        philosopherThread5.start();
    }

输出 :

4等待获取筷子left进行吃饭
1等待获取筷子left进行吃饭
3等待获取筷子left进行吃饭
5等待获取筷子left进行吃饭
2等待获取筷子left进行吃饭

这是一种死锁。

换个方式:

一 同时对两把筷子加锁,正规写法是定义全局变量

 public static class PhilosopherThread extends Thread {

        private Chopsticks left;

        private Chopsticks right;

        private int index;

        public PhilosopherThread(Chopsticks left, Chopsticks right, int index) {
            this.left = left;
            this.index = index;
            this.right = right;
        }

        @Override
        public void run() {
            synchronized (left.toString()+right.toString()) {
                try {
                    Thread.sleep(3000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(index + "等待获取筷子RIGHT+left进行吃饭");
//                synchronized (right) {
//                    System.out.println(index + "获取筷子RIGHT进行吃饭");
//                }
            }



        }


    }

输出:

2等待获取筷子RIGHT+left进行吃饭
1等待获取筷子RIGHT+left进行吃饭
4等待获取筷子RIGHT+left进行吃饭
3等待获取筷子RIGHT+left进行吃饭
5等待获取筷子RIGHT+left进行吃饭

二 奇偶互反

 奇偶互反,奇数哲学家先取右边,偶数先取左边。

 public static class PhilosopherThread extends Thread {

        private Chopsticks left;

        private Chopsticks right;

        private int index;

        public PhilosopherThread(Chopsticks left, Chopsticks right, int index) {
            this.left = left;
            this.index = index;
            this.right = right;
        }

        @Override
        public void run() {

            if(index%2==0) {
                synchronized (left) {
                    try {
                        Thread.sleep(3000L);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    synchronized (right) {
                        System.out.println(index + "吃完了");
                    }
                }
            }else{
                synchronized (right) {
                    try {
                        Thread.sleep(3000L);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    synchronized (left) {
                        System.out.println(index + "吃完了");
                    }
                }
            }


        }


    }

输出 :

3吃完了
5吃完了
1吃完了
4吃完了
2吃完了