古典的な問題シングルレーンブリッジ問題の飢餓のないソリューション

WebStormer:

私はシングルレーンブリッジは二つの村を結ぶクラシックシングルレーン橋の問題への解決策を提供しようとしています。それだけで1つのスレッドを使用しますので、農家は同時に橋の両側にジャンプする場合はデッドロックになることができます。これは、これまでの私の解決策ですが、私はそれ飢餓のないようにする方法を確認していませんか?

public class SingleLaneBridge {

  public static void main(String[] args)
  {
    final Bridge bridge = new Bridge();

    Thread thNorthbound = new Thread( new Runnable() {

      @Override
      public void run() {

        while(true) {
          Farmer farmer = new Farmer(bridge);
          Thread th = new Thread(farmer);
          farmer.setName("North Farmer : "+ th.getId());
          th.start();
          try {
            TimeUnit.SECONDS.sleep((long)(Math.random()*10));
          } catch(InterruptedException iex) {
            iex.printStackTrace();
          }
        }

      }
    });

    Thread thSouthbound = new Thread( new Runnable() {

      @Override
      public void run() {

        while(true) {
          Farmer farmer = new Farmer(bridge);
          Thread th = new Thread(farmer);
          farmer.setName("South Farmer : "+th.getId());
          th.start();
          try {
            TimeUnit.SECONDS.sleep((long)(Math.random()*10));
          }
          catch(InterruptedException iex)
          {
            iex.printStackTrace();
          }
        }
      }
    });

    thNorthbound.start();
    thSouthbound.start();
  }

}

class Bridge {
  private final Semaphore semaphore;

  public Bridge() {
    semaphore = new Semaphore(1);
  }
  public void crossBridge(Farmer farmer) {
    try {
      System.out.printf("Farmer trying to cross the bridge.\n",farmer.getName());
      semaphore.acquire();
      System.out.printf("Farmer crossing the bridge.\n",farmer.getName());
      long duration = (long)(Math.random() * 10);
      TimeUnit.SECONDS.sleep(duration);
    }
    catch(InterruptedException iex) {
      iex.printStackTrace();
    }
    finally {
      System.out.printf("Farmer as crossed the bridge.\n",farmer.getName());
      semaphore.release();
    }
  }
}

class Farmer implements Runnable
{
  private String name;
  private Bridge bridge;

  public Farmer(Bridge bridge)
  {
    this.bridge = bridge;
  }

  public void run() {
    bridge.crossBridge(this);
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }
}
ruakh:

まず、免責事項:あなたの質問の一部は本当に意味がありませんが、私はそれが誤解するよりも、専門用語の誤用に起因するよりかもしれないと思う、それ自体があなたは明確にあなたの質問を伝え、あなたが読んで何の意味を作りたい場合は残念ながら、専門用語は実際には非常に重要です。私は以下の私の最善を尽くしてきましたが、それは私があなたの本当の問題を誤解してることはかなり可能です。


これは、一つのスレッドだけ[...]を使用しています

私はあなたが何を意味するかわかりません。それは実際にすべての単一の農家のために別のスレッドを起動します。

それ[...]農家が同時に橋の両側にジャンプする場合はデッドロックになることができます。

それは正しくありません。ここでの唯一のロック機構は、単一のセマフォで、許可証を取得し、任意のスレッドがそうの可能性がない、それを獲得するために、再度試みる前にそれを解放することが保証されてデッドロックが


私はあなたのコードで3つの主要な問題を参照してください。

  1. あなたの導入は、シングルレーンブリッジをモデル化しようとしていることを示唆しています。それは本当に私が「シングルレーンブリッジ」の概念を理解し、少なくともとして、それをしません。具体的に:
    • あなたのコードは、任意の時点でブリッジを使用する唯一の農民を可能にします。全てが同じ方向に橋を渡るしたい多くの農家は、「シングル車線橋」がある場合はそれを可能にします。(A「は、単一レーンブリッジは、」のみに交差から二つの農民を防ぐ必要があり、反対方向)。
      • この問題は、あなたがあなたのソリューションは、「一つのスレッドだけを使用しています」と言ったとき、あなたは何を意味ですか?
    • 農家場合はFGは両方とも同じ方向に向かっている、と農家Fは、農家の前に到着したG、Iは「シングルレーンブリッジは」農家持っていることはないと思うGの農家の前にクロスをFあなたのコードは、しかし、その保証を提供していません。(NBは、この保証は、唯一の見出し農家に適用され、同じ農家がに向かっている場合。方向を方向、農家得るために有効であるかもしれないGは、すでに農家と同じ方向向かう別の農家があります場合は、最初に行くGを。それはのための設計上の決定ですあなたのようにします。)
  2. あなたのコードは、呼び出すacquiretry-ブロックした後、呼び出し、release対応にfinally-ブロック。それは、スレッドがそのスレッドが正常に許可証を取得したことがない場合でも、許可を解除することができることを意味しているから、安全ではありません。スレッドならば(そうでは、例えば、Tは、許可証を保持し、スレッドUVは両方の許可証を取得するために待っている、その後の呼び出しThread.interruptスレッドでは、Uは、スレッドが発生しますUをスローするようにInterruptedException、リリーススレッドTこれにより、スレッドをさせる、の許可をVすぐに許可証を取得!)
  3. 平均して、1軒の農家がブリッジを使用している時間の量で、二つの新しい農民は、各方向に移動するものを表示します。以来、あなたは唯一、1軒の農家が一度にブリッジを使用することができ、あなたがより多くの農家のブリッジを使用することを待っていると、さらに、さらに背後に落下しておこうというこの手段(前述したように)。
    • この問題は、あなたがあなたのソリューションは、「飢餓フリー」ではないことを言ったとき、あなたは何を意味ですか?

しかし、あなたの特定の質問に答えるために:

[...]私はそれ飢餓のないようにする方法を確認していませんか?

あなたが書く場合new Semaphore(1, true)だけではなく、のnew Semaphore(1)(あなたがセマフォの「公平性パラメータ」を設定している場合、すなわち、true)、そして、あなたのセマフォは、農家は、彼らが到着した順にブリッジを使用することができることを保証します。各農家が前の農家がそれをリリースしているようにすぐに許可証を取得することが保証されますので、これは、何の農家-スレッドが餓死しないことを保証します。

それでも場所でその公平性パラメータで、あなたはまだ農家はあなたがそれらを介して取得することができますよりも早く現れておくことを問題(前述)を持っています。これは、あなたが持っているように見えになるかもしれないリソース不足の問題は、本当に問題は、あなたがそれを使用しようとしている方法のための十分なリソースを持っていないだけということです。

この問題を解決するには、あなたは本当に長い間、彼らが同じ方向に移動しているとすると同時に、橋を渡るために、複数の農家を#1上記の修正発行する必要があり、許可します。私のようなカウンティングセマフォがないと思うjava.util.concurrent.Semaphoreそれをカットしようとしています。あなたが最大であることを保証する必要がある場合、そのクラスは便利ですnは許す任意の時点で取得されていますが、あなたの場合には、すべての所有者が同じ方向に移動している限り、取得することができ許可の数に制限はありません。

代わりに、私はあなたが次のようなものをしたいと思います:

  • AtomicIntegerまたは現在交差する権限を持っているどのように多くの農家追跡に似て。
  • 一つのスレッドセーフList旅行北回りに待機している農家の、および旅行南に待機している農家の一つ。
  • Farmer それはブリッジを使用する許可を持っているかどうかを示すブール値のフラグを持っています。
  • 農家が現れた場合、ブリッジはすでに使用されている場合、彼らは適切なリストに自分自身を追加し、入力synchronized/のwait旗がに設定されるまでループをtrue
  • 農家が橋の使用を終了するとき、彼らは更新しAtomicInteger、それが今ではゼロだ場合、彼らは任意の待機中の農家をチェックし、それらを覚まします。

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=362942&siteId=1