leetcode 1226. 哲学家进餐

这是避免死锁的一个经典题目,虽然算法知道,但是一直没有写过代码,这里总结一下主要的实现方法。

方法一,限制每次只能有一个哲学家吃饭,这种方法效率比较低,但是实现起来很简单,就是采用一个全局锁。本质上是同时获取所有的资源,而不是分步获取资源,打破持有并等待。

class DiningPhilosophers1 {
    ReentrantLock lock=new ReentrantLock();
    public DiningPhilosophers1() {
    }
    // 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 {
        lock.lock();
        pickLeftFork.run();
        pickRightFork.run();
        eat.run();
        putLeftFork.run();
        putRightFork.run();
        lock.unlock();
    }
}

方法二、规定序号为奇数的哲学家先拿左边的叉子,再拿右边的叉子,序号为偶数的哲学家则反过来,这样能够保证不会出现5个哲学家同时拿到左边叉子或右边叉子的死锁情况。打破循环等待的问题。

class DiningPhilosophers2 {
    ReentrantLock[] locks=new ReentrantLock[5];//5只叉子的锁
    public DiningPhilosophers2() {
        for(int i=0;i<5;i++){
            locks[i]=new ReentrantLock();
        }
    }
    // 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 {
        if((philosopher&1)==1){
            locks[philosopher].lock();
            locks[(philosopher-1+5)%5].lock();
        }else{
            locks[(philosopher-1+5)%5].lock();
            locks[philosopher].lock();
        }
        pickLeftFork.run();
        pickRightFork.run();
        eat.run();
        putLeftFork.run();
        putRightFork.run();
        locks[philosopher].unlock();
        locks[(philosopher-1+5)%5].unlock();
    }
}

方法三,限制同时吃饭的人数不超过4个人,这样总会产生两个人竞争一把叉子并竞争成功的情况,避免循环等待。

class DiningPhilosophers {
    Semaphore semaphore=new Semaphore(4);
    ReentrantLock[] locks=new ReentrantLock[5];
    public DiningPhilosophers() {
        for(int i=0;i<5;i++){
            locks[i]=new ReentrantLock();
        }
    }
    // 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 {
        semaphore.acquire();
        locks[philosopher].lock();
        locks[(philosopher-1+5)%5].lock();
        pickLeftFork.run();
        pickRightFork.run();
        eat.run();
        putLeftFork.run();
        putRightFork.run();
        locks[philosopher].unlock();
        locks[(philosopher-1+5)%5].unlock();
        semaphore.release();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值