少了一些什么代码?有人能看出来吗?
class DiningPhilosophers {
private final ReentrantLock[] lockList = {new ReentrantLock(),
new ReentrantLock(),
new ReentrantLock(),
new ReentrantLock(),
new ReentrantLock()};
public DiningPhilosophers() {
}
public void wantsToEat(int philosopher,
Runnable pickLeftFork,
Runnable pickRightFork,
Runnable eat,
Runnable putLeftFork,
Runnable putRightFork) throws InterruptedException {
int leftFork = (philosopher + 1) % 5;
int rightFork = philosopher;
if (philosopher % 2 == 0) {
lockList[leftFork].lock();
lockList[rightFork].lock();
}
else {
lockList[rightFork].lock();
lockList[leftFork].lock();
}
pickLeftFork.run();
pickRightFork.run();
eat.run();
putLeftFork.run();
putRightFork.run();
lockList[leftFork].unlock();
lockList[rightFork].unlock();
}
}
我需要详细代码
int rightFork = philosopher;
这里要%5,不然会数组越界
int rightFork = philosopher % 5;
然后就是runnable对象,启动应该用Thread包装,再调用start(),而不是直接调用run()方法。
缺少了判断左右筷子是否在使用吧
看了很久,这就是正确答案呀,没有错吧?
少了while条件判断https://blog.csdn.net/weixin_53236070/article/details/123628789
完整代码
// 解决方案(1)
class DiningPhilosophers {
//1个Fork视为1个ReentrantLock,5个叉子即5个ReentrantLock,将其都放入数组中
private final ReentrantLock[] lockList = {new ReentrantLock(),
new ReentrantLock(),
new ReentrantLock(),
new ReentrantLock(),
new ReentrantLock()};
//限制 最多只有4个哲学家去持有叉子
private Semaphore eatLimit = new Semaphore(4);
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 {
int leftFork = (philosopher + 1) % 5; //左边的叉子 的编号
int rightFork = philosopher; //右边的叉子 的编号
eatLimit.acquire(); //限制的人数 -1
lockList[leftFork].lock(); //拿起左边的叉子
lockList[rightFork].lock(); //拿起右边的叉子
pickLeftFork.run(); //拿起左边的叉子 的具体执行
pickRightFork.run(); //拿起右边的叉子 的具体执行
eat.run(); //吃意大利面 的具体执行
putLeftFork.run(); //放下左边的叉子 的具体执行
putRightFork.run(); //放下右边的叉子 的具体执行
lockList[leftFork].unlock(); //放下左边的叉子
lockList[rightFork].unlock(); //放下右边的叉子
eatLimit.release();//限制的人数 +1
}
}
// 解决方案(2)
class DiningPhilosophers {
//1个Fork视为1个ReentrantLock,5个叉子即5个ReentrantLock,将其都放入数组中
private final ReentrantLock[] lockList = {new ReentrantLock(),
new ReentrantLock(),
new ReentrantLock(),
new ReentrantLock(),
new ReentrantLock()};
//让 1个哲学家可以 “同时”拿起2个叉子(搞个临界区)
private ReentrantLock pickBothForks = new ReentrantLock();
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 {
int leftFork = (philosopher + 1) % 5; //左边的叉子 的编号
int rightFork = philosopher; //右边的叉子 的编号
pickBothForks.lock(); //进入临界区
lockList[leftFork].lock(); //拿起左边的叉子
lockList[rightFork].lock(); //拿起右边的叉子
pickLeftFork.run(); //拿起左边的叉子 的具体执行
pickRightFork.run(); //拿起右边的叉子 的具体执行
pickBothForks.unlock(); //退出临界区
eat.run(); //吃意大利面 的具体执行
putLeftFork.run(); //放下左边的叉子 的具体执行
putRightFork.run(); //放下右边的叉子 的具体执行
lockList[leftFork].unlock(); //放下左边的叉子
lockList[rightFork].unlock(); //放下右边的叉子
}
}
// 解决方案(3)
class DiningPhilosophers {
//1个Fork视为1个ReentrantLock,5个叉子即5个ReentrantLock,将其都放入数组中
private final ReentrantLock[] lockList = {new ReentrantLock(),
new ReentrantLock(),
new ReentrantLock(),
new ReentrantLock(),
new ReentrantLock()};
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 {
int leftFork = (philosopher + 1) % 5; //左边的叉子 的编号
int rightFork = philosopher; //右边的叉子 的编号
//编号为偶数的哲学家,优先拿起左边的叉子,再拿起右边的叉子
if (philosopher % 2 == 0) {
lockList[leftFork].lock(); //拿起左边的叉子
lockList[rightFork].lock(); //拿起右边的叉子
}
//编号为奇数的哲学家,优先拿起右边的叉子,再拿起左边的叉子
else {
lockList[rightFork].lock(); //拿起右边的叉子
lockList[leftFork].lock(); //拿起左边的叉子
}
pickLeftFork.run(); //拿起左边的叉子 的具体执行
pickRightFork.run(); //拿起右边的叉子 的具体执行
eat.run(); //吃意大利面 的具体执行
putLeftFork.run(); //放下左边的叉子 的具体执行
putRightFork.run(); //放下右边的叉子 的具体执行
lockList[leftFork].unlock(); //放下左边的叉子
lockList[rightFork].unlock(); //放下右边的叉子
}
}
// 解决方案(4)
class DiningPhilosophers {
//初始化为0, 二进制表示则为00000, 说明当前所有叉子都未被使用
private AtomicInteger fork = new AtomicInteger(0);
//每个叉子的int值(即二进制的00001, 00010, 00100, 01000, 10000)
private final int[] forkMask = new int[]{1, 2, 4, 8, 16};
//限制 最多只有4个哲学家去持有叉子
private Semaphore eatLimit = new Semaphore(4);
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 {
int leftMask = forkMask[(philosopher + 1) % 5], rightMask = forkMask[philosopher];
eatLimit.acquire(); //限制的人数 -1
while (!pickFork(leftMask)) Thread.sleep(1); //拿起左边的叉子
while (!pickFork(rightMask)) Thread.sleep(1); //拿起右边的叉子
pickLeftFork.run(); //拿起左边的叉子 的具体执行
pickRightFork.run(); //拿起右边的叉子 的具体执行
eat.run(); //吃意大利面 的具体执行
putLeftFork.run(); //放下左边的叉子 的具体执行
putRightFork.run(); //放下右边的叉子 的具体执行
while (!putFork(leftMask)) Thread.sleep(1); //放下左边的叉子
while (!putFork(rightMask)) Thread.sleep(1); //放下右边的叉子
eatLimit.release(); //限制的人数 +1
}
private boolean pickFork(int mask) {
int expect = fork.get();
return (expect & mask) > 0 ? false : fork.compareAndSet(expect, expect ^ mask);
}
private boolean putFork(int mask) {
int expect = fork.get();
return fork.compareAndSet(expect, expect ^ mask);
}
}
// 解决方案(5)
class DiningPhilosophers {
//初始化为0, 二进制表示则为00000, 说明当前所有叉子都未被使用
private AtomicInteger fork = new AtomicInteger(0), both = new AtomicInteger(0);
//每个叉子的int值(即二进制的00001, 00010, 00100, 01000, 10000)
private final int[] forkMask = new int[]{1, 2, 4, 8, 16};
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 {
int leftMask = forkMask[(philosopher + 1) % 5], rightMask = forkMask[philosopher];
while (!both.compareAndSet(0, 1)) Thread.sleep(1); //进入临界区
while (!pickFork(leftMask)) Thread.sleep(1); //拿起左边的叉子
while (!pickFork(rightMask)) Thread.sleep(1); //拿起右边的叉子
pickLeftFork.run(); //拿起左边的叉子 的具体执行
pickRightFork.run(); //拿起右边的叉子 的具体执行
while (!both.compareAndSet(1, 0)) Thread.sleep(1); //退出临界区
eat.run(); //吃意大利面 的具体执行
putLeftFork.run(); //放下左边的叉子 的具体执行
putRightFork.run(); //放下右边的叉子 的具体执行
while (!putFork(rightMask)) Thread.sleep(1); //放下右边的叉子
while (!putFork(leftMask)) Thread.sleep(1); //放下左边的叉子
}
private boolean pickFork(int mask) {
int expect = fork.get();
return (expect & mask) > 0 ? false : fork.compareAndSet(expect, expect ^ mask);
}
private boolean putFork(int mask) {
int expect = fork.get();
return fork.compareAndSet(expect, expect ^ mask);
}
}
// 解决方案(6)
class DiningPhilosophers {
//初始化为0, 二进制表示则为00000, 说明当前所有叉子都未被使用
private AtomicInteger fork = new AtomicInteger(0);
//每个叉子的int值(即二进制的00001, 00010, 00100, 01000, 10000)
private final int[] forkMask = new int[]{1, 2, 4, 8, 16};
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 {
int leftMask = forkMask[(philosopher + 1) % 5], rightMask = forkMask[philosopher];
//编号为偶数的哲学家,优先拿起左边的叉子,再拿起右边的叉子
if (philosopher % 2 == 0) {
while (!pickFork(leftMask)) Thread.sleep(1); //拿起左边的叉子
while (!pickFork(rightMask)) Thread.sleep(1); //拿起右边的叉子
}//编号为奇数的哲学家,优先拿起右边的叉子,再拿起左边的叉子
else {
while (!pickFork(rightMask)) Thread.sleep(1); //拿起右边的叉子
while (!pickFork(leftMask)) Thread.sleep(1); //拿起左边的叉子
}
pickLeftFork.run(); //拿起左边的叉子 的具体执行
pickRightFork.run(); //拿起右边的叉子 的具体执行
eat.run(); //吃意大利面 的具体执行
putLeftFork.run(); //放下左边的叉子 的具体执行
putRightFork.run(); //放下右边的叉子 的具体执行
while (!putFork(rightMask)) Thread.sleep(1); //放下右边的叉子
while (!putFork(leftMask)) Thread.sleep(1); //放下左边的叉子
}
private boolean pickFork(int mask) {
int expect = fork.get();
return (expect & mask) > 0 ? false : fork.compareAndSet(expect, expect ^ mask);
}
private boolean putFork(int mask) {
int expect = fork.get();
return fork.compareAndSet(expect, expect ^ mask);
}
}
// 解决方案(7)
class DiningPhilosophers {
private int[] leftFork = new int[5];
private int[] rightFork = new int[5];
private Object leftObj = new Object();
private Object rightObj = 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 (leftObj) {
while (checkLeftFork(philosopher)) {
leftObj.wait();
}
lockLeftFork(philosopher);
pickLeftFork.run();
leftObj.notifyAll();
}
synchronized (rightObj) {
while (checkRightFork(philosopher)) {
rightObj.wait();
}
lockRightFork(philosopher);
pickRightFork.run();
rightObj.notifyAll();
}
eat.run();
synchronized (leftObj) {
putLeftFork.run();
unlockLeftFork(philosopher);
leftObj.notifyAll();
}
synchronized (rightObj) {
putRightFork.run();
unlockRightFork(philosopher);
rightObj.notifyAll();
}
}
private void lockLeftFork(int philosopher) {
leftFork[philosopher] = 1;
}
private void lockRightFork(int philosopher) {
rightFork[philosopher] = 1;
}
private void unlockLeftFork(int philosopher) {
leftFork[philosopher] = 0;
}
private void unlockRightFork(int philosopher) {
rightFork[philosopher] = 0;
}
private boolean checkLeftFork(int philosopher) {
return rightFork[leftPhil(philosopher)] == 1 ? true : false;
}
private boolean checkRightFork(int philosopher) {
return leftFork[rightPhil(philosopher)] == 1 ? true : false;
}
private int leftPhil(int philosopher) {
return (philosopher + 1) % 5;
}
private int rightPhil(int philosopher) {
return (philosopher - 1 + 5) % 5;
}
}