fa Java garantisce che gli aggiornamenti elementi dell'array fatto da filo A prima di memorizzare il riferimento matrice in un AtomicReference
sarà sempre visibile per filo B che ottiene questo riferimento?AtomicReference di matrice e la matrice elemento cambia visibilità
In altre parole, quali sono le possibili uscite di esecuzione di questo:
class References {
AtomicReference<String[]> refs = new AtomicReference<>(new String[]{"first"});
public void add(String s) {
refs.updateAndGet(oldRefs -> {
String[] newRefs = new String[oldRefs.length + 1];
System.arraycopy(oldRefs, 0, newRefs, 0, oldRefs.length);
newRefs[oldRefs.length] = s;
return newRefs;
});
}
public static void main(String[] args) {
References r = new References();
new Thread(() -> r.add("second")).start();
System.out.println(Arrays.toString(r.refs.get()));
}
}
può quanto sopra stampare solo sia [first]
o [first, second]
, o è anche possibile ottenere risultati come [first, null]
o [null, null]
?
Javadoc per java.util.concurrent.atomic
stati:
compareAndSet
e tutte le altre operazioni di lettura e di aggiornamento comegetAndIncrement
hanno gli effetti di memoria di lettura e scrittura di variabili volatili.
che sembra non fornire alcuna garanzia per gli elementi non volatile dell'array, solo il riferimento di matrice stesso.
Otterrai sempre "{" prima "," seconda "}'; 'System.arrayCopy()' non ritorna prima che abbia completato il suo compito (sarebbe altrimenti inaffidabile altrimenti!) – fge
Se hai assegnato l'array a un campo 'final', avresti una tale garanzia, con' AtomicReference "Non penso che tu lo faccia. – biziclop
A proposito, probabilmente userei 'CopyOnWriteArrayList', che ti dà tutte le garanzie che puoi aspettarti da una tale collezione. – biziclop