synchronized 位置问题

来源:5-14 高阶并发编程Coding训练:N种优化哲学家就餐问题的方法(2)

HotChoc

2021-06-07

老师,synchronized 是不是不应该加在两个 Overide 的 take 方法上,那样锁住的是每个 Phi 实例,对于 forks 不能起到保护作用吧?
下面是我的代码

public class DiningPhilosophersDeadLock {

    Phi[] phis;
    volatile int[] forks;

    static final int NUM = 5;

    final Object lock = new Object();

    public DiningPhilosophersDeadLock() {
        phis = new Phi[NUM];
        forks = new int[NUM];
        
        for (int i = 0; i < NUM; i++) {
            phis[i] = new Phi(i + 1);
        }
    }

    class Phi extends Philosopher {
        Phi(int id) {
            super(id);
        }

        @Override
        protected boolean takeLeft(int[] forks) {
            synchronized (lock) {
                return super.takeLeft(forks);
            }
        }

        @Override
        protected boolean takeRight(int[] forks) {
            synchronized (lock) {
                return super.takeRight(forks);
            }
        }

        @Override
        public void run() {
            while (true) {
                try {
                    thinking();
                    while (!takeLeft(forks)) {
                        Thread.onSpinWait();
                    }
//                    System.out.println("take left");
                    Thread.sleep(100);
                    int c = 0;
                    // 这种方法虽然解决了 dead lock, 但小概率可能触发 live lock(所有线程都拿起了左叉子, 然后一起放下)
                    while (!takeRight(forks)) {
                        if (++c > 100) {
                            putLeft(forks);
                            continue;
                        }
                        Thread.onSpinWait();
                    }
//                    System.out.println("take right");
                    eating();
                    putLeft(forks);
                    putRight(forks);
                    finish();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void run() {
        ExecutorService pool = Executors.newFixedThreadPool(NUM);
        for (Phi phi : phis) {
            pool.submit(phi);
        }
    }

    public static void main(String[] args) {
        DiningPhilosophersDeadLock solver = new DiningPhilosophersDeadLock();
        solver.run();
    }
}
写回答

2回答

weixin_慕少1467281

2023-09-07

这个课程的代码真是一堆问题,字符串判断直接用 == ,我都要傻眼了
0
0

求老仙

2021-06-25

现在的锁相当于所有phi对象公用的。保护的是forks数组。

0
0

笑傲Java面试 剖析大厂高频面试真题 秒变offer收割机

深度剖析大厂面试高频真题,让你秒变offer收割机

1783 学习 · 314 问题

查看课程