2009-03-03 12 views
5

私はダイエットの哲学者の問題でセマフォの基本的なジストを学ぼうとしています。今、私はクラス箸の配列を持ち、それぞれの箸は1つの利用できる許可証を持つセマフォを持っていますJavaのダイエット哲学者とのセマフォの問題

public class Chopstick 
{ 
    Thread holder = null; 
    private Semaphore lock = new Semaphore(1); 

    public synchronized void take() throws InterruptedException 
    { 
     this.lock.acquire(); 
     holder = Thread.currentThread(); 

    } 

    public synchronized void release() 
    { 
     this.lock.release(); 
     holder = null; 
    } 
} 

ホルダー変数が、私は私が必要かわからない機能のために使用されます。

public synchronized void conditionalRelease() 
{ 
    if (holder == Thread.currentThread()) 
    { 
     holder = null; 
     this.lock.release(); 
    } 
} 

プログラムはコンパイルされて実行されますが、箸を放すには問題があるようです。時には、箸が解放されることもあれば、しないこともあります。彼らが解放されなければ、プログラムは最終的にすべての箸が取られ、1人の哲学者が空腹になるとハングアップします。ここで

は、ランダムな時間後に箸を解放する哲学者のクラス内のコードです:

System.out.println(this.name + " is eating"); 
Thread.sleep(this.getRandTime()); 
System.out.println(this.name + " has finished eating"); 

rightChopstick.release(); 
System.out.println(this.name + " has released the right chopstick"); 
leftChopstick.release(); 
System.out.println(this.name + " has released the left chopstick"); 

私のプログラムが出力例えば、「哲学者0は、食べ終わった」、および実行を継続ありません。他の2行は決して出力されないので、明らかに私がリリースしている方法で何かが間違っています。

何か助けていただければ幸いです。

答えて

8

私はあなたのメソッドシグネチャから 'synchronized'キーワードを取り出します。外部ロック機構(この場合はセマフォー)を使用しています。 'synchronized'キーワードは、オブジェクト自身のmutexを使用してロックを取得しようとしています。デッドロックの原因と思われる2つのリソースをロックしています。

+0

ハ!それはまさにそれでした...割り当てのためにこの2つの異なる方法を実装しなければならず、最初のメソッドのコードをコピーして貼り付け、synchronizedキーワードを削除するのを忘れました。ニースを見つける。 –

1

問題は、スレッド1が同じものを得るために、特定の箸と別の試行を持っているとき、それはラインthis.lock.acquire();take() -methodにお待ちしておりますが、それはがオブジェクト自体にモニターを解放しないだろうということです。

スレッド1が箸を解放しようとすると、まだrelease()というメソッドを入力することはできません。これは、まだ他のスレッドがtake()で待機しているためにロックされているためです。それはデッドロックです

1

あなたが箸でロックして、それがサイズ1のセマフォを保持するのはちょっと混乱しているようです。一般に、セマフォはリソースへのチケットを提供します。チケットが1つだけあれば、これはロック(同期ブロックまたはLockオブジェクトのいずれか)と同じです。実際には、箸をオブジェクト自体にすることを検討することもできます。

他の戦略を使ってデッドロックを回避する方法については実際には興味を持っていますが、私はJavaで食事をしている哲学者のブログ記事を投稿しました。

+0

これは、セマフォーを使用しなければならないと言っているクッキー要件がある宿題の一部だったようです。 –

+0

もう一つは、実際にはセプタフォ(またはロック)を拡張することです。 :)それはあなたにそれを直接使用すること以外何も買わないでしょうが。 –

0

Philospherは、開始前に食べるの両方chosticksのロックを取得する必要があり、ピックアップleftone最初に待つ右そこそこ方法を同期する必要があります起動食べ始めるだろう。 以下の方法はそれを動作させるだろう。

public synchronized void startEating() { 
    leftChopstick.acquire(); 
    rightChopstick.acquire(); 
} 

public void finishEating(int id) { 
    leftChopstick.release(); 
    rightChopstick.release(); 
} 
1

は、任意のロックまたは使用synchronizedキーワード何がないことを確認してください。チョップスティックの下のコードは私のためにうまく動作します..プロではなく、あなたにいくつかのアイデアを与えなければなりません。

public class Chopstick { 
private boolean inuse; 
Semaphore sem; 

public Chopstick(){ 

    inuse = false; 
    sem = new Semaphore(1); 
} 
public void pickUp() 
{ 
    try 
    { 
     while(inuse) 
     { 
      try 
      { 
       sem.acquire(); 

      } 
      catch(InterruptedException e) {} 
     } 
     inuse = true; 
    }catch(Exception e){} 
} 
public void putDown() 
{ 
    try 
    { 
     inuse = false; 
     sem.release(); 

    } 
    catch (Exception e){} 
} 

}

関連する問題