哲学家进餐问题,代码缺少,求帮助~

少了一些什么代码?有人能看出来吗?
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;
    }
}