Stavo cercando di creare un tipo di dati immutabile con campi finali (incluso un array costruito e riempito prima di essere assegnato al campo membro finale) e ho notato che sembra che la JVM sia specificata per garantire che qualsiasi altro thread che ottiene un riferimento a questo oggetto vedrà i campi inizializzati e i valori dell'array (supponendo che non siano pubblicati puntatori a this
all'interno del costruttore, vedere What is an "incompletely constructed object"? e How do JVM's implicit memory barriers behave when chaining constructors?).In che modo i campi finali impediscono ad altri thread di vedere oggetti parzialmente costruiti?
Sono curioso di sapere come ottenere questo risultato senza sincronizzare tutti gli accessi a questo oggetto, o altrimenti pagare una significativa penalizzazione delle prestazioni. Secondo la mia comprensione, la JVM può raggiungere questo obiettivo facendo quanto segue:
- Emettere un write-recinto, alla fine del costruttore
- Pubblicare il riferimento al nuovo oggetto solo dopo la scrittura-recinto
- il rilascio di un recinto di lettura ogni volta che si fa riferimento a un campo finale di un oggetto
non riesco a pensare a un modo più semplice o meno costosi di eliminare il rischio di altri thread vedere campi finali non inizializzate (o riferimenti ricorsivi attraverso campi finali).
Sembra che potrebbe imporre una severa penalizzazione delle prestazioni a causa di tutti i read-fences negli altri thread che leggono l'oggetto, ma eliminando le read-fences si introduce la possibilità che il riferimento all'oggetto venga visto in un altro processore prima di esso emette un read-fence o visualizza in altro modo gli aggiornamenti alle posizioni di memoria corrispondenti ai campi finali appena inizializzati.
Qualcuno sa come funziona? E se questo introduce una significativa penalizzazione delle prestazioni?
Chiarimento relativo a una risposta cancellata: Per quanto riguarda i problemi di prestazioni che ho, non mi occupo di problemi di prestazioni algoritmiche relative a strutture di dati immutabili in generale, solo con il degrado delle prestazioni derivante dalle istruzioni di membarrier. È vero che un thread potrebbe "sapere" che una volta emesso un read-fence quando accede a un tale oggetto, non deve emettere ulteriori read-fences per quello stesso oggetto, ma non è chiaro se o come ciò sia fatto, o se c'è un altro modo per ottenere i "campi finali inizializzati", garanzia che non riesco a pensare. – jonderry
capito, ecco perché l'ho cancellato. –