solución libre de la inanición del clásico problema de un solo carril del puente Problema

WebStormer:

Estoy intentando dar una solución al clásico problema de un solo carril del puente, donde un solo carril de puente conecta dos pueblos. Sólo se utiliza un hilo y así puede convertirse en un punto muerto si los agricultores saltar a uno y otro lado del puente al mismo tiempo. Esta es mi solución hasta el momento, pero no estoy seguro de cómo hacer que la inanición libre?

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:

En primer lugar, un descargo de responsabilidad: partes de su pregunta realmente no tienen sentido, pero creo que podría deberse más a un mal uso de la terminología que a malentendidos per se . Por desgracia, la terminología es en realidad muy importante si se quiere comunicar su pregunta clara y dar sentido a lo que lee. He hecho mi mejor más adelante, pero es muy posible que estoy malentendido su verdadera cuestión.


Sólo se utiliza un hilo [...]

No estoy seguro de lo que quieres decir; lo que realmente pone en marcha un hilo separado para cada agricultor.

Se [...] puede convertirse en un punto muerto si los agricultores saltar a uno y otro lado del puente al mismo tiempo.

Eso no es correcto; el único mecanismo de bloqueo que aquí hay una sola semáforo, y cualquier tema que adquiere un permiso está garantizado para liberarlo antes de intentarlo de nuevo para adquirirlo, así que no hay posibilidad de estancamiento .


Veo tres problemas importantes con su código:

  1. Su introducción sugiere que está tratando de modelar un puente de un solo carril; pero en realidad no hace que, al menos como yo entiendo el concepto de un "puente de un solo carril". Específicamente:
    • Su código sólo permite un agricultor a utilizar el puente en un momento dado; pero si hay muchos agricultores que todos queremos cruzar el puente en la misma dirección, a continuación, un "puente de un solo carril" permitiría eso. (A "puente de un solo carril" sólo debe evitar que dos agricultores de cruzar en opuestas direcciones.)
      • Es este tema lo que quería decir cuando dijo que su solución "sólo utiliza un hilo"?
    • Si los agricultores F y G se dirigen tanto a la misma dirección, y el agricultor F llega antes agricultor G , creo que un "puente de un solo carril" nunca tendría agricultor G cruz antes agricultor F . Su código, sin embargo, no proporciona esa garantía. (Nota: Esta garantía sólo se aplica a los agricultores que dirigen la misma dirección. Si los agricultores van en opuestas direcciones, podría ser válida para obtener agricultor G ir primero si ya hay otro agricultor al frente de la misma dirección que los agricultores G . Esa es una decisión de diseño para a hacer.)
  2. El código llama acquireen un try-bloque, y luego llama releaseen el correspondiente finally-bloque. Eso no es seguro, ya que significa que un hilo puede liberar un permiso incluso si ese hilo nunca adquirió con éxito un permiso. (Así, por ejemplo, si el hilo T tiene el permiso y las discusiones U y V son a la vez de espera para adquirir el permiso, a continuación, una llamada a Thread.interrupten la rosca T hará que el hilo T de lanzar un InterruptedExceptionhilo y la liberación T permiso 's, hilo dejando de ese modo V inmediato adquirir el permiso!)
  3. En promedio, la cantidad de tiempo que un agricultor utiliza el puente, dos nuevos agricultores se mostrarán, un viaje en cada dirección. Puesto que (como se mencionó anteriormente) que sólo permiten un agricultor a utilizar el puente a la vez, esto significa que usted va a seguir cayendo cada vez más atrás, con más y más agricultores esperando para usar el puente.
    • Es este tema lo que quería decir cuando dijo que su solución no es "hambre-libre"?

Pero para responder a su pregunta específica:

[...] No estoy seguro de cómo hacer que la inanición libre?

Si se escribe new Semaphore(1, true)en lugar de sólo new Semaphore(1)(es decir, si se establece "parámetro de equidad" del semáforo a true), entonces su semáforos se asegurará de que los agricultores pueden utilizar el puente en el orden en que llegan. Esto garantizará que ningún agricultor-hilo se morirá de hambre, porque cada agricultor estará garantizada para adquirir el permiso tan pronto como el granjero anterior lo ha publicado.

. . . pero incluso con ese parámetro equidad en su lugar, usted todavía tiene el problema (mencionado anteriormente) que los agricultores siguen apareciendo más rápido que se puede obtener a través de ellos. Esto podría hacer que se vea como que tiene un agotamiento de recursos problema, pero en realidad el problema es sólo que usted no tiene suficiente del recurso de cómo se está tratando de usarlo.

Para solucionar este problema, que realmente necesita para fijar tema # 1 anterior, y permitir que varios agricultores de cruzar el puente, al mismo tiempo, siempre y cuando están viajando en la misma dirección. No creo que un semáforo de cuenta como java.util.concurrent.Semaphorese va a cortar; que la clase es útil si es necesario asegurarse de que a lo sumo n permisos se adquieren en un momento dado, pero en su caso no hay ninguna restricción sobre el número de permisos que pueden ser adquiridos, siempre y cuando todos los titulares están viajando en la misma dirección.

En cambio, creo que querrá algo como lo siguiente:

  • Una AtomicIntegero similar a realizar un seguimiento de cuántos agricultores actualmente tiene permiso para cruzar.
  • Una multi-hilo Listde los agricultores a la espera de los viajes hacia el norte, y uno de los agricultores hacia el sur a la espera de los viajes.
  • Farmer tiene un indicador booleano para indicar si tiene permiso para utilizar el puente.
  • Cuando los agricultores se presenta, si el puente ya está en uso, que se suman a la lista apropiada, entran en un synchronized/ waitbucle hasta que su indicador se establece true.
  • Cuando los agricultores termine de utilizar el puente, se ponen al día el AtomicInteger, y si es ahora cero, comprueban en los Productores de espera y despertarlos.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=362945&siteId=1
Recomendado
Clasificación