问题

问题描述:一圆桌前坐着5位哲学家,两个人中间有一只筷子,桌子中央有面条。哲学家思考问题,当饿了的时候拿起左右两只筷子吃饭,必须拿到两只筷子才能吃饭。上述问题会产生死锁的情况,当5个哲学家都拿起自己右手边的筷子,准备拿左手边的筷子时产生死锁现象。

这里写图片描述

代码

代码逻辑:
多少个哲学家,就有多少个筷子,判断哲学家左右两边的筷子是否正在使用,如果正在被使用,则将当前哲学家阻塞起来

哲学家:

public class philosopher extends Thread{ 
 
    private String id; 
    private Chopsticks chopsticks; 
 
    public philosopher(String id, Chopsticks chopsticks){ 
        this.id = id; 
        super.setName(id); 
        this.chopsticks = chopsticks; 
    } 
 
    public void eat(){ 
        System.out.println("哲学家-" + id + " is eating"); 
        try { 
            sleep(10000); 
        } catch (InterruptedException e) { 
            e.printStackTrace(); 
        } 
    } 
 
    public void think(){ 
        System.out.println("哲学家-" + id + " is thinking"); 
        try { 
            sleep(10000); 
        } catch (InterruptedException e) { 
            e.printStackTrace(); 
        } 
    } 
 
    @Override 
    public void run() { 
        //think(); 
        chopsticks.take(); 
        eat(); 
        chopsticks.put(); 
    } 
}

筷子类:

class Chopsticks { 
 
    private boolean[] used; 
    private int count; 
    private Lock lock = new ReentrantLock(); 
    private Condition condition = lock.newCondition(); 
 
    public Chopsticks(int count) { 
        this.count = count; 
        used = new boolean[count]; 
        for (int i = 0; i < used.length; i++) { 
            used[i] = false; 
        } 
    } 
 
    public void take() { 
        lock.lock(); 
        try { 
            int i = Integer.parseInt(Thread.currentThread().getName()); 
            //只要左边或右边的筷子被拿走了,就一直阻塞 
            while (used[i] || used[ (i+1)%count ]) { 
                condition.await(); 
            } 
            System.out.println("take: " + i + ", " + (i+1)%count); 
            used[i] = true; 
            used[ (i+1)%count ] = true; 
        } catch (Exception e) { 
            e.printStackTrace(); 
        } finally { 
            lock.unlock(); 
        } 
    } 
 
    public void put() { 
        lock.lock(); 
        try { 
            int i = Integer.parseInt(Thread.currentThread().getName()); 
            used[i] = false; 
            used[ (i+1)%count ] = false; 
 
            //唤醒所有阻塞的哲学家 
            condition.signalAll(); 
            System.out.println("put: " + i + ", " + (i+1)%count); 
        } finally { 
            lock.unlock(); 
        } 
    } 
}

测试类:

class Test{ 
 
    public static void main(String[] args) { 
        Chopsticks chopsticks = new Chopsticks(5); 
        for (int i = 0; i < 5; i++) { 
            new philosopher(i+"", chopsticks).start(); 
        } 
    } 
}

结果:

take: 0, 1 
take: 2, 3 
哲学家-2 is eating 
哲学家-0 is eating 
put: 0, 1 
put: 2, 3 
take: 1, 2 
哲学家-1 is eating 
take: 3, 4 
哲学家-3 is eating 
put: 3, 4 
put: 1, 2 
take: 4, 0 
哲学家-4 is eating 
put: 4, 0
发布评论

分享到:

IT虾米网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!

jstack简单使用,定位死循环、线程阻塞、死锁等问题详解
你是第一个吃螃蟹的人
发表评论

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。