2012-07-13 17 views
5

Considerate seguente codice, voglio renderla una classe thread-safe, in modo che non potrà mai ottenere il numero dispari:posso utilizzare sincronizzato su un campo finale?

class Test { 
    private int value = 0; 
    private final Object lock; 

    public void add() { 
    synchronized (lock) { 
     value++; 
     value++; 
    } 
    } 

    public int getValue() { 
    synchronized (lock) { 
     return value; 
    } 
    } 
} 

Ora sono dubbi del campo di blocco, che viene dichiarata definitiva, sarà questo importa? o romperà la sicurezza del filo?

Penso che se il campo di blocco non è dichiarato definitivo, questa dovrebbe essere una classe thread-safe. Se questa conclusione è sbagliata, per favore correggimi, grazie.

+0

Vedere [questo] (http://stackoverflow.com/questions/2101327/final-variable-and-synchronized-block-in-java) domanda. – Lion

risposta

9

Ora ho dubbi sul campo di blocco, che è dichiarato definitivo, sarà questo?

Sì, la sua migliore prassi considerata solo bloccare final oggetti campo.

Se è possibile modificare il riferimento, è possibile modificare l'oggetto bloccato, interrompendo la sicurezza del filo.

0

In Java la sinconizzazione viene eseguita da un campo nascosto dell'oggetto blocco. Anche i mezzi finali, che il RIFERIMENTO è finale, non l'oggetto stesso.

Esempio:

final Bar bar = new Bar(); //bar hase property lock 
bar.lock = XYZ; //will work, object is not FINAL 
bar = new Bar(); //fail, the reference is FINAL 
+0

Per quello che vale, non esiste un costrutto integrato per rendere gli 'oggetti finali' in Java. L'immutabilità deve essere applicata a livello di codice. – corsiKa

1

dovrebbe essere ok. potrebbe persino renderlo più sicuro, poiché non si può semplicemente assegnare qualcos'altro al blocco durante l'esecuzione.

1

Se stai cercando di bloccare un esempio, allora finale è accettabile. Dovresti cercare di bloccare o mettere un mutex in una classe, quindi rendere la variabile statica.

0

Quando si tenta di sincronizzare più thread, devono essere sincronizzati in base allo stesso riferimento/istanza dell'oggetto. Ciò garantisce che entrambi si sincronizzino contemporaneamente sulla base degli stessi dati.

Spero che abbia un po 'di senso; devi solo sincronizzare basato su una variabile finalizzata piuttosto che su una dinamica.

Se un metodo modifica un campo statico, è necessario sincronizzare l'accesso a questo campo, anche se il metodo è tipicamente usato solo da un singolo thread. Non è possibile per i client eseguire la sincronizzazione esterna con tale metodo poiché non è possibile garantire che i client non correlati facciano altrettanto, see.