力扣1226.哲学家进餐

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

(1)互斥条件:一个资源每次只能被一个进程使用。
(2)占有且等待:进程已经占有了至少一个资源,同时请求新资源而被阻塞时,对已获得的资源保持不放。
(3)不可强行占有:进程已获得的资源,在末使用完之前,不能强行剥夺。
(4)循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

设第i个哲学家,他左边的筷子为i,右边为(i+1)%5

1.加一个同步锁,把并发变为顺序执行

class DiningPhilosophers {

    private Object obj = new Object();

    public DiningPhilosophers() {
        
    }

    // call the run() method of any runnable to execute its code
    public void wantsToEat(int philosopher,
                           Runnable pickLeftFork,
                           Runnable pickRightFork,
                           Runnable eat,
                           Runnable putLeftFork,
                           Runnable putRightFork) throws InterruptedException {
        synchronized(obj){
            pickLeftFork.run();
            pickRightFork.run();
            eat.run();
            putLeftFork.run();
            putRightFork.run();
        }
    }
}

感觉类似于同时只允许一个人进餐(?)

2.

class DiningPhilosophers {
        private ReentrantLock lock = new ReentrantLock();
        private Condition[] conditions = new Condition[5];
        private boolean[] forks = new boolean[5];

        public DiningPhilosophers() {
        for (int i=0;i<5;i++){
            conditions[i] = lock.newCondition();
        }
    }


    // call the run() method of any runnable to execute its code
    public void wantsToEat(int philosopher,
                           Runnable pickLeftFork,
                           Runnable pickRightFork,
                           Runnable eat,
                           Runnable putLeftFork,
                           Runnable putRightFork) throws InterruptedException {
        lock.lock();
        try{
            int leftFork = philosopher;
            int rightFork = (philosopher + 1) % 5;

//任意左右叉子被占用,开始等待
            while(forks[leftFork]||forks[rightFork]){
                conditions[philosopher].await();
            }
            forks[leftFork]=true;
            forks[rightFork]=true;
            pickLeftFork.run();
            pickRightFork.run();
            eat.run();
            putLeftFork.run();
            forks[leftFork]=false;
            conditions[leftFork].signal();
            putRightFork.run();
            forks[rightFork]=false;
            conditions[rightFork].signal();
        }
        finally{
            lock.unlock();
        }
    }
}

申请筷子得不到满足则放下筷子过段时间再申请

上一篇:tcache poisoning(爆破stout获得libc并且熟练使用了realloc)


下一篇:PuppeteerSharp Docker 中运行报错解决方案