2013-06-23 85 views
3

這是我的哲學家晚餐併發問題的實現。我只爲兩個線程工作,其餘的人從飢餓中逐字地獲得;)我很感激你能否找到它的原因。飢餓發生在餐飲哲學家代碼

下面是輸出:

Philosopher 2 is eating 
Philosopher 0 is eating 
Philosopher 2 is eating 
Philosopher 0 is eating 
Philosopher 2 is eating 
Philosopher 0 is eating 
Philosopher 2 is eating 
Philosopher 0 is eating 
Philosopher 2 is eating 
Philosopher 2 is eating 
Philosopher 0 is eating 
Philosopher 2 is eating 
Philosopher 0 is eating 

下面的代碼:

public class PhilosophersDinner { 

    public static void main(String[] args) { 
     Chopstick2[] chopsticks = new Chopstick2[5]; 
     Philosopher [] philosophers = new Philosopher[5]; 

     for (int i = 0; i < 5; i++) { 
      Chopstick2 stick = new Chopstick2(); 
      chopsticks[i] = stick; 
     } 

     for (int i = 0; i < 5; i++) { 
      Philosopher philo = new Philosopher(chopsticks[i] , chopsticks[(i+1)%5], i+""); 
      philosophers[i] = philo; 
     } 

     for (int i = 0; i < philosophers.length; i++) { 
      new Thread(philosophers[i]).start(); 
     } 
    } 

} 

class Philosopher implements Runnable { 

    private final Chopstick2 left; 
    private final Chopstick2 right; 
    private final String id; 

    public Philosopher(Chopstick2 l, Chopstick2 r, String id){ 
     this.left = l; 
     this.right = r; 
     this.id = id; 
    } 

    public void eat(){ 
     if (left.pickUp()) { 
      if (right.pickUp()) { 
       chew(); 
       putDown(); 
      } else left.putDown(); 
     } 
    } 


    public void run(){ 
     for (int i = 0; i < 10; i++) { 
      eat(); 
     } 
    } 

    public void chew(){ 
     try { 
      System.out.println("Philosopher "+id+" is eating"); 
      Thread.sleep(400); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
      // release lock here? 
     } 
    } 

    public void putDown(){ 
     left.putDown(); 
     right.putDown(); 
    } 

} 

class Chopstick2 { 
    private volatile boolean taken = false; 

    public synchronized boolean pickUp(){ 
     if (!taken) { 
      taken = true; 
      return true; 
     } 
     else return false; 
    } 

    public synchronized void putDown(){ 
     taken = false; 
    } 
} 
+1

我只是簡單地看了一下代碼,但這個問題的經典解決方案是至少有一個右手哲學家和至少一個左手,這將避免死鎖。爲了避免經典飢餓,你需要實現一個監視器(一個信號量和一個隊列結合)。 –

+0

謝謝你指出傑克,但如果左筷子被釋放時,如果右筷子被拿走,它怎麼會陷入僵局? – ksiomelo

回答

1

的問題是,前兩個Philosophers拿到筷子花了第二飲食的一半,在此期間,其他三個食客嘗試吃,直到他們放棄和戒菸。

一個解決方案是讓所有哲學家都吃一段時間,而不是進行特定次數的嘗試。

for (long i = System.currentTimeMillis()+10000; i > System.currentTimeMillis();) { 
     eat(); 
    } 
+0

應該是'>'。更好的是,用一個體面的變量名稱和一個「while」循環替換它。 – erickson

+0

謝謝蒂姆,解決了這個問題! – ksiomelo