2012-05-15 4 views
12

Non sono sicuro se la parola chiave volatile debba essere utilizzata anche per i non primitivi. Ho un membro della classe che viene impostato/assegnato da un thread e accessibile da un altro thread. Devo dichiarare questo membro volatile?java - parola chiave volatile anche per non primitivi

private /* volatile */ Object o; 

public void setMember(Object o) { 
    this.o = o; 
} 

public Object getMember() { 
    return o; 
} 

Qui, setMember (...) viene chiamato da un thread e getMember() viene chiamato da un altro.

Se fosse un booleano, ad esempio, la risposta sarebbe sì.

Sto utilizzando Java 1.4 e il membro in questo caso è di sola lettura. Quindi mi preoccupo solo della visibilità in questo caso, da qui la mia domanda sulla parola chiave volatile.

risposta

11

Sì - volatile ha esattamente lo stesso significato per i campi di tipo di riferimento che ha per i campi di tipo primitivo. Tranne che nel caso dei tipi di riferimento, i membri dell'oggetto che il campo fa riferimento a devono essere progettati anche per l'accesso multi-thread.

+0

semplicemente curiosi di scoprire questa dichiarazione - i membri dell'oggetto del campo si riferisce deve anche essere progettato per l'accesso multi-threaded - sarebbe bello se si potesse espandere il motivo per cui è così? – jtkSource

+0

@jtkSource: volatile riguarda solo il campo, ma il campo contiene solo un riferimento. Così volatile assicura che gli altri thread vedano aggiornamenti a quel riferimento, ma se l'oggetto di riferimento non usa volatile o la sincronizzazione correttamente, allora altri thread potrebbero non riuscire a vedere gli aggiornamenti dei campi di quell'oggetto. –

+0

solo a pensarci - quindi se una variabile volatile si riferisce a un oggetto, le variabili non volatili non sarebbero anche rese "visibili" in modo coerente all'interno del contesto dell'oggetto che lo ha dichiarato volatile? Se ci sono altri oggetti che si riferiscono a questo "oggetto riferito" in modo non volatile, solo gli oggetti potrebbero rischiare di non vedere la variabile in uno stato coerente? ci sarebbe una possibilità che ci siano due rappresentazioni dello stesso oggetto in memoria? - Fammi sapere se ho confuso la mia logica. – jtkSource

6

È possibile e potrebbe essere utile, ma ricordare la parola chiave si applica solo all'impostazione del riferimento. Non ha alcun effetto sulla visibilità multi-thread delle proprietà all'interno di quell'oggetto. Se è stato, probabilmente vuoi sincronizzarti attorno ad ogni accesso ad esso in ogni caso, per assicurarti le relazioni desiderate prima di accadere.

4

Sì, il codice è corretto. In questo caso il riferimento stesso è volatile, quindi le possibilità di riferimento sono automaticamente visibili in tutti gli altri thread, ma non le modifiche all'oggetto a cui si fa riferimento.

0

Se guardiamo AtomicInteger classe, ha dichiarato value come volatile, quindi può essere utilizzato in ambiente multi-threaded senza alcun problema cache dei processi.

public class AtomicInteger { 
    private volatile int value; 

    /** 
    * Gets the current value. 
    * 
    * @return the current value 
    */ 
    public final int get() { 
     return value; 
    } 

    /** 
    * Sets to the given value. 
    * 
    * @param newValue the new value 
    */ 
    public final void set(int newValue) { 
     value = newValue; 
    } 

} 

Ma se si pensa riferimento ad esso AtomicInteger scaffale sarà modificata con diversi oggetti AtomicInteger da molti fili; quindi hai bisogno di volatile anche per quel riferimento.

private volatile AtomicInteger reference = new AtomicInteger(0); 

Principalmente non sarà il caso; verrà modificato solo il valore dell'oggetto; quindi dichiaralo come finale.

private final AtomicInteger reference = new AtomicInteger(0);