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
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." –
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