5

Sto leggendo sul doppio blocco di controllo da Effective Java.
Il codice esegue le seguenti operazioni:In che modo l'assegnazione a una variabile locale aiuta qui?

private volatile FieldType field; 
FieldType getField() { 
    FieldType result = field; 
    if (result == null) { // First check (no locking) 
     synchronized(this) { 
     result = field; 
     if (result == null) // Second check (with locking) 
      field = result = computeFieldValue(); 
     } 
    } 
    return result; 
}  

Si dice che l'uso result sembra non necessari, ma assicura che in realtà il field è di sola lettura solo una volta nel caso comune in cui è già inizializzato.
Ma non lo capisco.
Qual è la differenza con fare if(field == null) direttamente?
Non capisco perché if (result == null) è diverso, figuriamoci meglio come affermato.
Qualche aiuto per capire questo per favore?

+2

Il 'risultato' viene utilizzato ulteriormente nel metodo? –

+1

Ci piacerebbe vedere "etc" ... Qual è il riferimento di pagina per Java efficace? Non ho la mia copia con me - ma altri potrebbero. –

+0

@VictorSorokin: vedere l'aggiornamento – Jim

risposta

4

Il pensiero in quell'esempio è che il risultato/campo sarà usato più di una volta più in basso credo. L'accesso a result è più economico (non è volatile).

Si ha una seconda lettura volatile quando si effettua il ritorno in caso contrario.

Utilizzare il modello di inizializzazione su richiesta invece se necessario. http://en.wikipedia.org/wiki/Initialization_on_demand_holder_idiom

Aggiungendo alcuni dei miei chiarimenti nei commenti alla risposta se stesso per ben ... chiarezza:

Versione corta: Una variabile locale può essere solo in un registro a (uno dei) CPU (s) (e in uno dei core della CPU se più, ecc.). È veloce come prima. Una variabile volatile deve essere controllata per le modifiche in altri core/cache/cpus/memoria, ma i dettagli possono essere molto specifici dell'hardware (linee della cache, barriere della memoria, ecc.).Ma anche jvm specifico, (il compilatore del server hotspot potrebbe sollevare variabili non volatili per esempio) e impone limiti sulle istruzioni di riordino per i possibili guadagni in termini di prestazioni

+0

Si potrebbe voler dire cosa implica "volatile", in Java: http://en.wikipedia.org/wiki/Volatile_variable#In_Java – ArjunShankar

+0

@Pulsar: Quindi è più costoso accedere a un 'volatile'? – Jim

+0

@Jim - sì. Leggi il link che ho incollato sopra. – ArjunShankar

5

La spiegazione è nella pagina successiva (enfasi da me):

cosa questa variabile non è quello di garantire che il campo è leggere una sola volta nell'arco caso comune in cui è già inizializzato. Sebbene non sia necessario , può migliorare le prestazioni ed è più elegante in base agli standard applicati alla programmazione concorrente di basso livello. Sulla mia macchina, il metodo precedente è circa il 25 percento più veloce della versione ovvia senza una variabile locale.

Per riferimento, la citazione è da p. 284 dell'articolo 71: Utilizzare l'inizializzazione lenta in modo giudizioso in Seconda edizione Java efficace.

Aggiornamento: la differenza tra la lettura di un locale vs una variabile volatile è che il primo può essere ottimizzato meglio. Le variabili volatili non possono essere memorizzate in registri o cache, né operazioni di memoria su di essi riordinate. Inoltre, la lettura di una variabile volatile può attivare la sincronizzazione della memoria tra diversi thread.

Vedi Java Concurrency in Practice, sezione 3.1.4: variabili volatili per maggiori dettagli.

+2

Questo in realtà non risponde alla domanda e l'OP sembra aver già visto questa spiegazione. – assylias

+0

@assylias, in che modo "questo potrebbe migliorare le prestazioni" non rispondere alla domanda ??? –

+1

Penso che la domanda sia: come migliora le prestazioni? – assylias

Problemi correlati