import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class DiningPhilosophers {

    public static void main(String[] args) {
        Lock[] forks = new ReentrantLock[5];
        for (int i = 0; i < 5; i++) {
            forks[i] = new ReentrantLock();
        }

        Philosopher[] philosophers = new Philosopher[5];
        for (int i = 0; i < 5; i++) {
            philosophers[i] = new Philosopher(i, forks[i], forks[(i + 1) % 5]);
        }

        for (Philosopher philosopher : philosophers) {
            philosopher.start();
        }
    }

    static class Philosopher extends Thread {
        private int id;
        private Lock leftFork;
        private Lock rightFork;

        public Philosopher(int id, Lock leftFork, Lock rightFork) {
            this.id = id;
            this.leftFork = leftFork;
            this.rightFork = rightFork;
        }

        public void run() {
            while (true) {
                think();
                pickUpLeftFork();
                pickUpRightFork();
                eat();
                putDownRightFork();
                putDownLeftFork();
            }
        }

        private void think() {
            System.out.println('Philosopher ' + id + ' is thinking');
            try {
                Thread.sleep((long) (Math.random() * 5000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        private void eat() {
            System.out.println('Philosopher ' + id + ' is eating');
            try {
                Thread.sleep((long) (Math.random() * 5000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        private void pickUpLeftFork() {
            leftFork.lock();
            System.out.println('Philosopher ' + id + ' picked up left fork');
        }

        private void pickUpRightFork() {
            rightFork.lock();
            System.out.println('Philosopher ' + id + ' picked up right fork');
        }

        private void putDownLeftFork() {
            leftFork.unlock();
            System.out.println('Philosopher ' + id + ' put down left fork');
        }

        private void putDownRightFork() {
            rightFork.unlock();
            System.out.println('Philosopher ' + id + ' put down right fork');
        }
    }
}

本代码使用 ReentrantLock 解决哲学家进餐问题中的死锁问题。每个哲学家拥有一个左叉和一个右叉,他们需要同时拿起两个叉子才能吃饭。如果哲学家按顺序拿起叉子,就会出现死锁。

本代码中,每个叉子都用一个 ReentrantLock 对象表示。每个哲学家在拿起叉子时都会先尝试获取左叉的锁,如果获取成功,则尝试获取右叉的锁。如果获取右叉的锁失败,则会释放左叉的锁,并再次尝试获取右叉的锁。

通过这种方式,可以避免死锁的发生。

代码说明:

  • DiningPhilosophers 类是主类,负责创建哲学家和叉子对象,并启动每个哲学家的线程。
  • Philosopher 类代表一个哲学家,它拥有一个 id、一个 leftFork 和一个 rightFork
  • run() 方法模拟哲学家的行为,包括思考、拿起叉子、吃饭、放下叉子。
  • think()eat() 方法模拟哲学家思考和吃饭的行为,并在其中随机休眠一段时间。
  • pickUpLeftFork()pickUpRightFork()putDownLeftFork()putDownRightFork() 方法分别用来拿起和放下叉子,并打印相应的日志信息。

运行结果:

程序运行后,你会看到每个哲学家会依次思考、拿起叉子、吃饭、放下叉子,循环往复。程序不会出现死锁,因为每个哲学家都能顺利地拿到两个叉子,并完成吃饭动作。

总结:

本代码使用 ReentrantLock 解决哲学家进餐问题中的死锁问题,并通过代码示例和详细的注释,帮助你理解如何使用 ReentrantLock 解决多线程编程中的死锁问题。

其他解决死锁的方法:

  • 使用信号量(Semaphore)
  • 使用条件变量(Condition)
  • 使用原子变量(Atomic)

建议:

  • 尝试使用不同的方法解决哲学家进餐问题,并比较它们的优缺点。
  • 阅读更多关于多线程编程和死锁的资料,深入理解相关概念。
Java 代码实现哲学家进餐问题 - 解决死锁问题

原文地址: https://www.cveoy.top/t/topic/ogpY 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录