2016-04-12 8 views
2

私はmultithreadingを学んでいますので、実装されていない解決策はありません。改善の提案は高く評価されています。マルチスレッドのシンプルデッドロックバグ検出回避

10,000フィートの概要:mainには、3つのパラメータ(スレッド、リソース、実行時の長さ)を指定できます。各スレッドはランダムな時間待ってから、リソースの解放を完了すると、ランダムな時間共有リソース/クリティカルセクションにアクセスすることを決定します。指定された実行時間の長さを繰り返し、すべてのスレッドを終了します。

ゴーカートトラックのユーザーの問題に基づいて、乗り物の間を交互に乗り降りします。

私はデッドロックを作成しましたが、その可能性はありません。

スリーパーは、スレッドをしばらく待つだけです。

ライダークラス:

public void run() { 
     while (!coord.exit) { 
      System.out.format("Rider %d is gone walkabout%n", ID); 
      Sleeper.walkAround(ID); 
      System.out.format("Rider %d is in line%n", ID); 
      try { 
      carID = coord.getInLine(); 
      System.out.format("Rider %d is riding car %d%n", ID, carID); 
      Sleeper.rideTime(ID); 
      coord.returnCar(carID); 
      } catch (InterruptedException ie) {System.out.println("Thread " + ID + " was interrupted.");} 
     } 
    } 

肉でありコーディネータークラスがある:ここ

public class Coordinator { 

    Rider[] riderArr; 
    Semaphore mutex = new Semaphore(1); 
    Semaphore cars; 
    LinkedList<Integer> carLine; 
    volatile static boolean exit = false; 

    public synchronized int getInLine() throws InterruptedException { 
     cars.acquire(); 
     mutex.acquire(); 
     int carid = carLine.removeFirst(); 
     mutex.release(); 
     return carid; 
    } 

    public synchronized void returnCar(int carID) throws InterruptedException { 
     mutex.acquire(); 
     carLine.add(carID); 
     mutex.release(); 
     cars.release(); 
    } 

    public Coordinator(int cars, int riders) { 
     riderArr = new Rider[riders]; 
     for (int i = 0; i < riders; i++) { 
      riderArr[i] = new Rider(this, i + 1); 
     } 
     carLine = new LinkedList<Integer>(); 
     for (int i = 0; i < cars; i++) { 
      carLine.add(i + 1); 
     } 
     this.cars = new Semaphore(cars); 
    } 

    public static void main(String[] args) throws NumberFormatException, InterruptedException { 
     Coordinator coord = new Coordinator(Integer.parseInt(args[0]), 
       Integer.parseInt(args[1])); 
     for (int i = 0; i < Integer.parseInt(args[1]); i++) { 
      coord.riderArr[i].start(); 
     } 
     Thread.sleep(1000 * Integer.parseInt(args[2])); 
     exit = true; 
     for (int i = 0; i < Integer.parseInt(args[1]); i++) { 
      coord.riderArr[i].join(); 
     } 
     System.exit(0); 
    } 
} 

はデッドロックセッションのコンソール出力である:ここ

Rider 2 is gone walkabout 
Rider 2 is walking around for 4 seconds 
Rider 1 is gone walkabout 
Rider 1 is walking around for 1 seconds 
Rider 1 is in line 
Rider 1 is riding car 1 
Rider 1 is riding for 3 seconds 
Rider 2 is in line 
+1

あなたの質問はありますか? – Natecat

+0

@natecatどのように2つの同期メソッドを指定するとスピンロックが発生しますか? –

+0

ええ、私はセマフォーがスピンロックとどのように似ているのか混乱しています。ここには疑問がないようですが、コードレビューサイトが良いと示唆しています。 http://codereview.stackexchange.com/ – markspace

答えて

3

でありますデッドロックシナリオ:

  • Nスレッドは、スレッドXがgetInLineが​​であり、Xがロックを有しているので、Nスレッドのいずれかにするための方法がないcars#acquire

ためgetInLine待機に入るcars

  • 内のすべてのN Semaphoreトークンを取得しますトークンを返す。

    public synchronized int removeCar(){ 
        return carLine.removeFirst(); 
    } 
    
    public synchronized void addCar(int car){ 
        carLine.add(car); 
    } 
    
    returnCar方法が自分の​​方法でcarLine#removeFirstcarLine#addを置き、他の2つの方法から​​を削除することですあなたの目標を達成するためのより良い方法も​​


    だからです

    これにより、mutexオブジェクトが不要になります。代わりにCoordinatorオブジェクト自体をミューテックスとして使用します。また、セマフォのacquireがトークンを返さないようにするのを待つことを意味します。

  • +0

    私はLinkedListsメソッドをオーバーライドしたくないので、私は 'synchronized'を削除してmutexを保持しました。私は「同期」したことを誤解していましたが、私はまだあまりにも曖昧ですが、私はそれをもっと調べます。ありがとう! –

    +1

    @DougClark Javaでは、任意のオブジェクトをミューテックス、または特にリエントラントロックとして使用できます。同期を使用するには2つの方法があります。 (クラスインスタンス全体をロックとして使用する)、または 'sychronized(obj){}'ブロック(ロックとして '()内のオブジェクトを使用する)のいずれかを使用します。 synchronizedを呼び出すスレッドは、メソッドがブロックを終了またはブロックを離れるまでオブジェクトにロックを持ちます。第1のスレッドがロックしている間に別のスレッドが 'synchronized'に達すると、第1のスレッドがロックを返すまで待機します。 – flakes

    関連する問題