2014-10-28 13 views
6

Al riguardo fondo http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html, si dice:perché gli oggetti immutabili sono sicuri nel bloccaggio a doppio controllo?

ricontrollato blocco Immutabile Oggetti

Se Helper è un oggetto immutabile, in modo tale che tutti i campi di Helper sono finali, quindi fare doppio il blocco di controllo funzionerà senza dover utilizzare campi volatili. L'idea è che un riferimento a un oggetto immutabile (come una stringa o un intero) debba comportarsi più o meno allo stesso modo di un oggetto int o float; leggere e scrivere i riferimenti a oggetti immutabili sono atomici.

Il campione e la spiegazione di una mutevole è la seguente:

// Broken multithreaded version 
// "Double-Checked Locking" idiom 
class Foo { 
    private Helper helper = null; 
    public Helper getHelper() { 
    if (helper == null) 
     synchronized(this) { 
     if (helper == null) 
      helper = new Helper(); 
     }  
    return helper; 
    } 
    // other functions and members... 
    } 

La prima ragione non funziona

La ragione più ovvia non è così funziona in modo che le scritture che inizializzano l'oggetto Helper e la scrittura nel campo helper possano essere eseguite o percepite in modo errato. Pertanto, un thread che richiama getHelper() potrebbe vedere un riferimento non nullo a un oggetto helper, ma vedere i valori predefiniti per i campi dell'oggetto helper, piuttosto che i valori impostati nel costruttore.

Se il compilatore inline la chiamata al costruttore, le scritture che inizializzano l'oggetto e la scrittura nel campo helper possono essere liberamente riordinate se il compilatore può provare che il costruttore non può lanciare un'eccezione o eseguire la sincronizzazione.

Anche se il compilatore non riordina quelle scritture, su un multiprocessore il processore o il sistema di memoria possono riordinare tali scritture, come percepito da un thread in esecuzione su un altro processore.

La mia domanda è: perché classe immutabile does't hanno il problema? Non riesco a vedere alcuna relazione del riordino se la classe è mutabile.

Grazie

risposta

0

Le classi immutabili hanno avuto il problema. La parte che hai citato è vera dopo le modifiche nella memoria Java sono state apportate in JSR133.

In particolare, le modifiche che interessano oggetti immutabili sono correlate ad alcune modifiche apportate alla parola chiave final. Cassa http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#finalRight.

La parte importante è:

I valori per campi finali di un oggetto sono impostate nel suo costruttore. Supponendo che l'oggetto sia costruito "correttamente", una volta costruito un oggetto, i valori assegnati ai campi finali nel costruttore saranno visibili a tutti gli altri thread senza sincronizzazione.

1

Il motivo per cui il codice è "spezzato" per gli oggetti abituali è che helper potrebbe essere non nulla, ma punto ad un oggetto che non è stato completamente inizializzato ancora come spiegato nel vostro preventivo.

Tuttavia se la classe Helper è immutabile, il che significa che tutti i suoi campi sono finali, the Java Memory Model garanzie che essi sono in modo sicuro pubblicati anche se l'oggetto è reso disponibile attraverso una gara di dati (che è il caso nel tuo esempio):

final i campi consentono inoltre ai programmatori di implementare oggetti immutabili sicuri per i thread senza sincronizzazione. Un oggetto immutabile sicuro per thread è considerato immutabile da tutti i thread, anche se viene utilizzata una sequenza di dati per passare i riferimenti all'oggetto immutabile tra i fili. Questo può fornire garanzie di sicurezza contro l'uso improprio di una classe immutabile da codice errato o malevolo. I campi final devono essere utilizzati correttamente per fornire una garanzia di immutabilità.

+0

Penso che il termine "completamente inizializzato" indichi qualcosa di diverso con quello del collegamento? "Un oggetto è considerato completamente inizializzato quando il suo costruttore termina e un thread che può vedere solo un riferimento a un oggetto dopo che l'oggetto è stato completamente inizializzato è garantito per vedere i valori correttamente inizializzati per i campi finali dell'oggetto." –

+0

No, è lo stesso: dopo la chiamata a 'new Helper()', il JMM garantisce che i campi finali sono stati inizializzati ma non dice nulla sui campi regolari che potrebbero o non sono stati inizializzati. – assylias

Problemi correlati