如大家所熟悉的,程序员在学操作系统的时候一般都会接触一个经典问题——哲学家进餐问题,有 5 个哲学家围着在一个圆桌上,而圆桌上正好放有 5 根筷子,每根筷子放在两个哲学家之间,就在这两个人的左 / 右手边,并且这两个哲学家都能拿起筷子,哲学家进餐有规定:每个人只能拿起左手边和右手边的筷子,如果没有两根筷子,就不能进餐,每个人进餐结束之后将筷子放回原处。

这个问题很考验程序员对线程同步的理解,感兴趣的读者可以自己先尝试编程实现。

以下是解题参考程序:

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");
        }
    }
}

总之,多线程是有很多知识点需要总结的,学习了多线程的概念和方法,还应当去实际场景中去应用,多敲多练才是掌握知识的最好方法。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐