2013-03-02 8 views
6

del codice Java:Il thread di codice di incremento seguente è sicuro in java?

public class IncreaseTest { 
    public static int value = 0; 

    public synchronized int increment() { 
     return value++; 
    } 
} 

è il metodo increment() thread-safe? Devo aggiungere la parola chiave modificatore volatile come segue:

public static volatile int value = 0; 
+0

È necessario specificare la lingua. – paxdiablo

+0

Grazie per avermelo ricordato – codeisee

risposta

18

Questo codice non è thread-safe. Il metodo di istanza si sincronizzerà su un'istanza, se si dispone di più istanze esse non utilizzeranno lo stesso monitor e quindi gli aggiornamenti possono essere intercalati.

È necessario rimuovere la statica dal campo value o aggiungere statico al metodo increment().

Inoltre, come è stato reso pubblico value, esiste il problema aggiuntivo che è possibile modificare o leggere il valore al di fuori di questo metodo senza utilizzare la sincronizzazione che potrebbe comportare la lettura di valori precedenti.

Quindi modificare il codice di seguito si renderà thread-safe:

public class IncreaseTest { 
    private int value = 0; 

    public synchronized int increment() { 
     return value++; 
    } 
} 
+0

(+1) Buon punto. Ho completamente trascurato il 'statico'. – NPE

+0

@NPE Così ho fatto inizialmente. –

+0

valore int privato = 0; // se rimuovere statico e cambiare pubblico a privato, quel thread è sicuro ?? – codeisee

0

Se si utilizza questo metodo in due thread, allora si ha bisogno la parola chiave volatile. Senza di esso, un altro thread potrebbe non ottenere il valore più aggiornato. (C#)

+0

La parola chiave sincronizzata nella dichiarazione del metodo è la stessa che ha un 'lock (this) {...}' in C#. –

1

non credo che questo è thread-safe in quanto la variabile statica è pubblico e si può accedere da altri thread in un non- filo sicuro modo. Per essere sicuri filo è necessario dichiarare la variabile come segue:

public static volatile int value; 

Ora value essendo volatile, si può accedere in un blocco sincronizzato.

+0

Rendere la variabile volatile è diverso dall'accedere da un blocco sincronizzato. L'operazione ++ non è ancora un'operazione atomica, anche se la variabile è volatile. –

+0

"L'accesso alla variabile agisce come se fosse racchiuso in un blocco sincronizzato, sincronizzato su se stesso." secondo [questo] (http://www.javamex.com/tutorials/synchronization_volatile.shtml) – niculare

+3

Il confronto nell'articolo è un cattivo, soggetto ad errori.In particolare, 'value ++' rende due diversi accessi al valore: uno per leggere il valore e un altro per scriverlo. Rendere volatile 'value' non garantirà che la lettura e la scrittura siano racchiuse in un'unica operazione atomica. Solo la sincronizzazione lo garantisce. Ciò significa che è possibile avere due thread che leggono in parallelo, quindi scrivono in parallelo, e il valore dovrebbe essere incrementato di 1 invece di essere incrementato di 2. –

0

Probabilmente si dovrebbe usare atomicvars

+0

I vars atomici non sono un vuoto per problemi di threading di per sé. IMHO è meglio capire cosa sta succedendo sotto il cofano. –