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();
}
后记
- 千古兴亡多少事?悠悠。不尽长江滚滚流。