Pregunta

Puedo empezar a aprender algo de java concurrencia concepto ans poner en uso.Pero uno de este trozo de código es más allá de mi entendimiento.

public class Count { 
    private int count = 0; 
    public synchronized void setCount(int count) { 
        this.count = count; 
    } 
    public synchronized int getCount() { 
        return count; 
    } 
} 
class CountRunner extends Thread { 
    Count count; 
    public CountRunner(Count count) { 
        this.count = count; 
    } 
    public void run() { 
        for (int i = 1; i <= 1000; i++) { 
            count.setCount(count.getCount() + 1); 
        } 
    } 
} 
class TestCount { 
    public static void main(String[] args) throws Exception { 
        Count count = new Count(); 
        CountRunner runnerA = new CountRunner(count); 
        CountRunner runnerB = new CountRunner(count); 
        runnerA.start(); 
        runnerB.start();         
        runnerA.join(); //join statement here 
        runnerB.join(); 
        System.out.println("count.getCount = " + count.getCount()); 
    } 
} 
Question:
1. The result is a little less than 2000 for many times, why ?
2. if delete 2 join() statement, why count.getCount = 451,even less ?
3. i think there will be no effect of deleting the join() statements,
because i already have Synchronized method to lock one object to one thread each time ? 
So, What's the point of using Synchronized and join() ?
¿Fue útil?

Solución

es bastante simple.Llame al método de SetCount llamando a GETCOUNT + 1. Antes de ingresar el método, el tiempo de ejecución evalúa la actualización (sincronizada), pero no mantiene la cerradura al salir de GetCount e ingresar a SetScount y otros subprocesos pueden ingresar una llamada GetCount.Entonces, de vez en cuando, dos (o más, según la cantidad de hilos que cree) tendrán el mismo valor en la actualidad.Imagínese un hilo que entra y recibe el valor 1 en GetCount.El tiempo de ejecución produce su ejecución para pisar b que llama a GetCount y recibe el mismo valor 1. El hilo B establece el valor a 1 y hace que otras 50 carreras, por lo que su cuenta sería 50 en esa etapa.El tiempo de ejecución produce la ejecución para subprocesar a aquel que llama a SetCount con 1 (recuerde que no se logró llamar a SetCount y le dio su ejecutivo).Ahora, A establece el valor a 1 (lo que está mal).

Cambiar usted ejecuta la implementación como esta:

public void run() { 
    for (int i = 1; i <= 1000; i++) {
      synchronized(count){ 
        count.setCount(count.getCount() + 1); 
      }
    } 
} 

Otros consejos

  1. Si rompe la línea

    conde.setcount (cuenta.getcount () + 1);

    en 3 líneas separadas, será más clara:

    final int oldCount = count.getCount(); // a
    final int newCount = oldCount + 1; // b
    count.setCount(newCount); // c
    

    Tenga en cuenta que, si bien las declaraciones (A) y (C) están sincronizadas, el bloque completo es no .Para que aún puedan intercalarse, lo que significa que el hilo A puede ingresar / ejecutar la declaración (a) después de que el hilo B ejecuta la rosca (A) pero antes de termina / entra en la instrucción (c).Cuando esto sucede, el hilo (A) y (b) tendrá el mismo OldCount y, en consecuencia, se pierde un incremento.

    2.

    Únete a () es asegurarse de que tanto los terminados de hilo A como los hilos antes de imprimir.La razón por la que está obteniendo un conteo más pequeño si, si es porque, cuando imprime el hilo de su resultado A y B, puede no haber terminado de funcionar hasta.En otras palabras, incluso si se sincroniza perfectamente, sin unirse (), todavía tendrá un número mucho más pequeño que el 2000.

    3. Ver respuesta a 2.

1) Porque no se cierre correctamente.Usted está llamando getCount(), que se bloquea, obtiene el valor de y se desbloquea, el incremento y llamadas setCount() que bloquea, guarda el valor y la abre.Lo que sucede en algunos casos es que los dos hilos de la llamada getCount(), la primera banda de rodadura de cerraduras, obtiene el valor xy se desbloquea.A continuación, el segundo hilo recibe el bloqueo, obtiene el mismo valor xy se desbloquea .Desde los dos hilos de incremento y posteriormente guardar el mismo valor, usted va a obtener un bajo conteo de lo esperado.

2) Sin join() no espere a que sus hilos para terminar, su principal hilo acaba de llamar getCount() y obtener un valor aleatorio, mientras que los hilos están aún en marcha.

3) Dado que los otros hilos que no se mantenga un bloqueo todo el tiempo (si usted quiere que ellos ejecutan, que necesitan para dar a cada uno de los otros desbloqueado tiempo, después de todo), tendrás la join()todavía.

someThread.join() hará la llamada Thread esperar hasta que someThread se ha completado.

Si se quita el join() llamadas, a continuación, los principales Thread puede llamar a getCount() antes de que el conteo es finalizado, porque someThread aún se estén ejecutando.

Un método sincronizado simplemente significa que más de una sincronizada llamada a un Object no se pueden hacer en el mismo tiempo.

La línea de respuesta es que count.setCount(count.getCount() + 1); no es una operación atómica.

O para ser un poco menos oracular, mientras que setCount y getCount son correctamente thread-safe y atómica, no hay nada que impida a otro hilo de llamar a cualquiera de esos métodos entre este hilo llamado a la setCount y getCount.Que dará como resultado un recuento de perderse.

Una manera de evitar la pérdida de cuenta es para crear una atómica increment() operación.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top