método Java omite a veces por uno de los hilos

bodich:

Tengo un problema cuando se utiliza el mismo método por 2 hilos .

El problema es: Parece que cuando un hilo llamado método, y el método se está ejecutando, y en el mismo tiempo que otro hilo intenta llamar al mismo método, Java simplemente omitir esa llamada ! Por lo tanto, cuando 2 hilos están pidiendo el mismo método, ese método se llama sólo una vez. Por lo tanto, a veces al azar Programm se omita método y código no se ejecuta en absoluto! ¿Como es posible? Intentado en diferentes máquinas, definitivamente no funciona como se esperaba y me parece un error tremendo de Java.

Por favor, si cualquier experto leerá esto, se puede describir lo que sucede y si es problema conocido, dame el enlace a la explicación. ¡Gracias!

PD: El código está en pleno funcionamiento, sólo puede pegar incluso a java en línea como repl.it o similar. Justo después de a.updateCounter (inc); Puedo comprobar si incrementador trabajó (línea 45).

class Main {
  public static void main(String[] args) {
    ThreadOne t1 = new ThreadOne(1000, 300, "Thread 1");
    ThreadOne t2 = new ThreadOne(1, 300, "Thread 2");
    Thread one = new Thread(t1);
    Thread two = new Thread(t2);
    one.start();
    two.start();
  }
}

class Accum {
  private static Accum a = new Accum();
  private int counter = 0;
  private Accum() {}
  public static Accum getAccum() {
    return a;
  }

  public void updateCounter(int add) {
    counter += add;
  }

  public int getCount() {
    return counter;
  }
}

class ThreadOne implements Runnable {
  Accum a = Accum.getAccum();
  int inc;
  int max;
  String threadName;

  ThreadOne(int i, int c, String name) {
    inc = i;
    max = c;
    threadName = name;
  }

  public void run() {
    for(int x = 0; x < max; x++) {
      int check = a.getCount();
      a.updateCounter(inc);
      if(check + inc != a.getCount()) System.out.println("\nupdateCounter was skipped at x " + x + "\nThread name: " + threadName);
      try {
        Thread.sleep(5);
      } catch(InterruptedException ex) {
        System.out.println("x: " + x + "\n ex: " + ex);
      }
    }
    System.out.println(threadName + ": " + a.getCount());
  }
}
Benoit:

En primer lugar, Java no se salta la llamada. Es sólo el resultado real que no coincide con su prueba.

Entre int check = a.getCount();y la prueba if(check + inc != a.getCount()), el contador se cambia simplemente por el otro hilo . Eso es tan simple como eso.

UPDATE: La operación counter += addno es ATOMIC , es decir, puede visualizarla como una secuencia de 3 operaciones:

  • El valor de counterque se lee
  • Un nuevo valor se calcula
  • Este nuevo valor se asigna a counter

Ahora imagine 2 hilos que realizan esta secuencia exactamente en el mismo tiempo, y se entiende por qué el valor no consigue incrementa.

Solución para hacer esta llamada atómica: Simplemente utilizar AtomicIntegersegún lo mencionado por @gudok:

import java.util.concurrent.atomic.AtomicInteger;

public class Accum {
    private static Accum a = new Accum();
    private AtomicInteger counter = new AtomicInteger(0);
    private Accum() {}
    public static Accum getAccum() {
        return a;
    }

    public void updateCounter(int add) {
        counter.addAndGet(add);
    }

    public int getCount() {
        return counter.intValue();
    }
}

Supongo que te gusta

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