Come l'altro thread può mostrare il valore incrementato a meno che il primo thread non raggiunga l'istruzione return?

0

Il mio codice è riportato di seguito.

Nel ciclo for sto ottenendo risultati inaspettati, ad esempio prima di completare l'esecuzione di for loop per 1st thread, il secondo thread entra in loop e mostra il valore incrementato.

public class ThreadSafe {
    public static void main(String[] args) throws InterruptedException {
        System.out.println("main()");

        B b=new B("1st Thread");
        B b1=new B("2nd Thread");
        B b2=new B("3rd Thread");
        b.start();
        b1.start();
        b2.start();
    }
}

class MyCounter {
    private static int count;

    public static int getCount(){
        for(int m=0;m<2;m++){
            System.out.println(count+" "+Thread.currentThread().getName());
        }

        return count++;
    }         
}

class B extends Thread{
    public B(String tname) {
        super(tname);
    }

public void run() {
    MyCounter.getCount();
    }
}

La domanda è quando il 1 ° thread viene eseguito per il ciclo, quindi altri thread che eseguono l'istruzione return è questa la ragione per mostrare il valore di incremento o qualcos'altro?

Quale altro thread può mostrare il valore incrementato a meno che il primo thread non raggiunga l'istruzione return?

    
posta Avi 15.05.2014 - 13:35
fonte

2 risposte

1

primi 2 punti da rendere:

  1. non è garantito che l'esecuzione del thread sia interlacciata, brevi parti di codice probabilmente completeranno ininterrottamente. Aggiungi posti letto se vuoi ridurre questo effetto.

  2. count++ non è thread-safe, si espande in int tmp=count; count=tmp+1; e il thread può essere interrotto tra tmp=count e count=tmp+1 . Utilizza invece un AtomicInt e incrementAndGet .

L'incremento del conteggio statico potrebbe non essere visibile all'altro thread, ci vuole un po 'prima che le modifiche a una variabile diventino visibili ad altri thread. L'utilizzo di un campo volatile lo ridurrà, ma vedrai comunque i punti 1 e 2 in vigore.

Anche le istruzioni di stampa vengono memorizzate nel buffer prima di essere scritte in modo che l'ordine delle istruzioni di stampa non significhi necessariamente che siano state chiamate in tale ordine.

    
risposta data 15.05.2014 - 13:54
fonte
0

Esempio di output :

0 1st Thread
1 3rd Thread
1 3rd Thread
2 1st Thread
0 2nd Thread
0 2nd Thread

Quello che vedi qui è che i tuoi thread hanno localmente memorizzato nella cache la tua variabile count , in quanto non è dichiarata come essere volatile :

When applied to a field, the Java volatile guarantees that:

(In all versions of Java) There is a global ordering on the reads and writes to a volatile variable. This implies that every thread accessing a volatile field will read its current value before continuing, instead of (potentially) using a cached value.

(emphasis mine)

Essere volatili non salverà il tuo contatore da comportamenti anomali sotto ++ però, in quanto non è un'operazione atomica :

[That] an increment expression, such as counter++, does not describe an atomic action. Even very simple expressions can define complex actions that can decompose into other actions[...] Atomic actions cannot be interleaved, so they can be used without fear of thread interference.

Il tutorial Java sulla concorrenza è un ottimo posto per conoscere queste cose.

    
risposta data 15.05.2014 - 23:51
fonte

Leggi altre domande sui tag