哲学家就餐问题-Java语言实现死锁避免

哲学家就餐问题-Java语言实现死锁避免

我死锁预防是至少破坏死锁产生的四个必要条件之一,带来的问题就是系统资源利用率低且不符合开发习惯,而死锁避免不是事先釆取某种限制措施破坏死锁的必要条件,只是注意避免死锁的最终发生。

哲学家就餐问题

5 个沉默寡言的哲学家围坐在圆桌前,每人面前一盘意面。叉子放在哲学家之间的桌面上。(5 个哲学家,5 根筷子)

所有的哲学家都只会在思考和进餐两种行为间交替。哲学家只有同时拿到左边和右边的筷子才能吃到面,而同一根筷子在同一时间只能被一个哲学家使用。每个哲学家吃完面后都需要把筷子放回桌面以供其他哲学家吃面。只要条件允许,哲学家可以拿起左边或者右边的筷子,但在没有同时拿到左右筷子时不能进食。

产生死锁的四个必要条件:

(1) 互斥条件:一个资源每次只能被一个进程使用。
(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3) 不可剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
(4) 环路等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
只要系统发生了死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。

解除死锁:从死锁进程处剥夺资源;终止部分或全部进程

Java语言实现死锁避免Demo

加锁前检查需要的资源是否足够,只有哲学家两边的筷子都没人用时同时拿起

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

class DiningPhilosophers {
    //5根筷子的状态,0代表未使用,1代表已使用
    public static int[] chopsticks = new int[5];
    public static ReentrantLock lock = new ReentrantLock();
    public static Condition condition = lock.newCondition();

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

    static class Philosophers implements Runnable {
        public int No;

        public Philosophers(int no) {
            No = no;
        }

        private void eat() {
            System.out.println("哲学家 " + No + " is eating");
            try {
                Thread.currentThread().sleep(1500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        private void think() {
            System.out.println("哲学家 " + No + " is thinking");
            try {
                Thread.currentThread().sleep(1500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        private void takeChopsticks() {
            lock.lock();
            //如果右边的筷子和左边的筷子都没有被使用
            if (chopsticks[No] == 0 && chopsticks[(No + 4) % 5] == 0) {
                chopsticks[No] = 1;
                chopsticks[(No + 4) % 5] = 1;
            } else {
                try {
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            lock.unlock();
        }

        private void putdownChopsticks() {
            lock.lock();
            chopsticks[No] = 0;
            chopsticks[(No + 4) % 5] = 0;
            condition.signalAll();
            lock.unlock();
        }

        @Override
        public void run() {
            while (true) {
                this.think();
                this.takeChopsticks();
                this.eat();
                this.putdownChopsticks();
            }
        }
    }
}
    /*      哲学家 0 is thinking
            哲学家 4 is thinking
            哲学家 1 is thinking
            哲学家 3 is thinking
            哲学家 2 is thinking
            哲学家 0 is eating
            哲学家 2 is eating
            哲学家 2 is thinking
            哲学家 0 is thinking
            哲学家 1 is eating
            哲学家 3 is eating
            哲学家 4 is eating
            哲学家 0 is eating
            哲学家 3 is thinking
            哲学家 2 is eating
            哲学家 1 is thinking
            ………………………………		*/

给锁添加时限:先拿起右边的筷子,再尝试拿左边的筷子,如果一段时间后依然没有拿到左边的筷子,则放下右边的筷子

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

class DiningPhilosophers2 {

    public static ReentrantLock[] chopsticks = new ReentrantLock[5];
    public static Condition[] conditions = new Condition[5];

    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            chopsticks[i] = new ReentrantLock();
            conditions[i] = chopsticks[i].newCondition();
        }
        for (int i = 0; i < 5; i++) {
            new Thread(new Philosophers(i)).start();
        }
    }

    static class Philosophers implements Runnable {

        public int No;

        public Philosophers(int no) {
            No = no;
        }

        private void eat() {
            System.out.println("哲学家 " + No + " is eating");
            try {
                Thread.currentThread().sleep(1500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        private void think() {
            System.out.println("哲学家 " + No + " is thinking");
            try {
                Thread.currentThread().sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        private void takeChopsticks() {
            //是否获取了两个筷子
            boolean acquire = false;
            while (true) {
                if (chopsticks[No].tryLock()) {
                    while (true) {
                        if (!chopsticks[(No + 4) % 5].tryLock()) {
                            chopsticks[No].unlock();
                            try {
                                Thread.currentThread().sleep(1000);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        } else {
                            acquire = true;
                        }
                        break;
                    }
                    if (acquire) {
                        chopsticks[(No + 4) % 5].unlock();
                        chopsticks[No].unlock();
                        break;
                    }

                }
            }
        }

        private void putdownChopsticks() {
            chopsticks[(No + 4) % 5].lock();
            chopsticks[No].lock();
            conditions[No].signalAll();
            conditions[(No + 4) % 5].signalAll();
            chopsticks[(No + 4) % 5].unlock();
            chopsticks[No].unlock();
        }

        @Override
        public void run() {
            while (true) {
                this.think();
                this.takeChopsticks();
                this.eat();
                this.putdownChopsticks();
            }
        }
    }
}
/*      哲学家 0 is thinking
        哲学家 2 is thinking
        哲学家 4 is thinking
        哲学家 1 is thinking
        哲学家 3 is thinking
        哲学家 0 is eating
        哲学家 2 is eating
        哲学家 1 is eating
        哲学家 3 is eating
        哲学家 4 is eating
        哲学家 0 is thinking
        哲学家 1 is thinking
        哲学家 2 is thinking
        哲学家 0 is eating
        哲学家 3 is thinking
        哲学家 4 is thinking
        哲学家 2 is eating
        哲学家 1 is eating
        哲学家 3 is eating
        哲学家 0 is thinking
        哲学家 2 is thinking
        哲学家 1 is thinking
        哲学家 4 is eating
        哲学家 0 is eating
        哲学家 3 is thinking
        哲学家 1 is eating
        哲学家 4 is thinking
        哲学家 2 is eating
        哲学家 3 is eating*/




posted @ 2021-09-01 18:35  aixueforever  阅读(526)  评论(0编辑  收藏  举报