春招打卡d9n14-leetcode刷题1226哲学家进餐

302 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

leetcode刷题1226哲学家进餐

前文

本文为leetcode多线程类型题目,题目序号为1226,主要考察多线程相关知识的应用。

题目信息

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

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

解题思路

根据题目要求分析,每个科学家都需要左右两把叉子。所以我们首先设置五把锁,分别代表5个餐具。当一个科学家需要吃东西时,首先判断两把锁的状态。只有当两把锁都可以获得时,才可以拿取餐具,而当进食完毕后,要进行两把锁的释放,方便其他人继续进食。由于哲学家时处于环形座位,因此要考虑餐具左右时需要进行取余数操作,防止位置溢出。按照这种方式便可实现题目中所要求的哲学家进餐。

解题代码

private ReentrantLock[] forks = new ReentrantLock[5];
public DiningPhilosophers() {
    for (int i = 0; i < forks.length; i++) {
        forks[i] = new ReentrantLock();
    }
}

// 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 {
    int fork1 = philosopher;
    int fork2 = (philosopher + 1) % 5;
    forks[Math.min(fork1,fork2)].lock();
    forks[Math.max(fork1,fork2)].lock();
    pickLeftFork.run();
    pickRightFork.run();
    eat.run();
    putLeftFork.run();
    putRightFork.run();
    forks[Math.min(fork1,fork2)].unlock();
    forks[Math.max(fork1,fork2)].unlock();
}

后记

  • 千古兴亡多少事?悠悠。不尽长江滚滚流。