哲學家就餐問題是1965年由Dijkstra提出的一種線程同步的問題。
問題描述:一圓桌前坐着5位哲學家,兩個人中間有一只筷子,桌子中央有面條。哲學家思考問題,當餓了的時候拿起左右兩只筷子吃飯,必須拿到兩只筷子才能吃飯。上述問題會產生死鎖的情況,當5個哲學家都拿起自己右手邊的筷子,准備拿左手邊的筷子時產生死鎖現象。
解決辦法:
1、添加一個服務生,只有當經過服務生同意之后才能拿筷子,服務生負責避免死鎖發生。
2、每個哲學家必須確定自己左右手的筷子都可用的時候,才能同時拿起兩只筷子進餐,吃完之后同時放下兩只筷子。
3、規定每個哲學家拿筷子時必須拿序號小的那只,這樣最后一位未拿到筷子的哲學家只剩下序號大的那只筷子,不能拿起,剩下的這只筷子就可以被其他哲學家使用,避免了死鎖。這種情況不能很好的利用資源。
代碼實現:實現第2種方案
package cn.edu.sdust.Philosopher; /*每個哲學家相當於一個線程*/ class Philosopher extends Thread{ private String name; private Fork fork; public Philosopher(String name,Fork fork){ super(name); this.name=name; this.fork=fork; } public void run(){ while(true){ thinking(); fork.takeFork(); eating(); fork.putFork(); } } public void eating(){ System.out.println("I am Eating:"+name); try { sleep(1000);//模擬吃飯,占用一段時間資源 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void thinking(){ System.out.println("I am Thinking:"+name); try { sleep(1000);//模擬思考 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } class Fork{ /*5只筷子,初始為都未被用*/ private boolean[] used={false,false,false,false,false,false}; /*只有當左右手的筷子都未被使用時,才允許獲取筷子,且必須同時獲取左右手筷子*/ public synchronized void takeFork(){ String name = Thread.currentThread().getName(); int i = Integer.parseInt(name); while(used[i]||used[(i+1)%5]){ try { wait();//如果左右手有一只正被使用,等待 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } used[i ]= true; used[(i+1)%5]=true; } /*必須同時釋放左右手的筷子*/ public synchronized void putFork(){ String name = Thread.currentThread().getName(); int i = Integer.parseInt(name); used[i ]= false; used[(i+1)%5]=false; notifyAll();//喚醒其他線程 } } //測試 public class ThreadTest { public static void main(String []args){ Fork fork = new Fork(); new Philosopher("0",fork).start(); new Philosopher("1",fork).start(); new Philosopher("2",fork).start(); new Philosopher("3",fork).start(); new Philosopher("4",fork).start(); } }
運行結果:
I am Thinking:0 I am Thinking:2 I am Thinking:3 I am Thinking:1 I am Thinking:4 I am Eating:0 I am Eating:2 I am Thinking:0 I am Eating:4 I am Thinking:2 I am Eating:1 I am Thinking:4 I am Eating:3 I am Thinking:1 I am Eating:0 I am Thinking:3 I am Eating:2 I am Thinking:0 I am Eating:4 I am Thinking:2 。。。。。。。。。。。。。
分析:上述解決方案解決了死鎖問題。可以看到最多只能有兩條相鄰的eating結果,因為每個時刻最多能夠滿足兩個人同時進餐,且兩人座位不相鄰。