Domanda relativa al JMM e alla semantica riguardante i campi volatili scritti in un blocco sincronizzato, ma letti non sincronizzati.Necessità di scrittura di array volatile mentre si è nel blocco sincronizzato
In una versione iniziale del codice seguente, non stavo sincronizzando l'accesso poiché non era necessario per i requisiti precedenti (e abusando di un'assegnazione automatica this.cache = this.cache assicurava una semantica volatile di scrittura). Alcuni requisiti sono stati modificati, rendendo necessaria la sincronizzazione per garantire che non vengano inviati aggiornamenti duplicati. La domanda che ho è che il blocco di sincronizzazione preclude di richiedere l'auto assegnazione del campo volatile?
// Cache of byte[] data by row and column.
private volatile byte[][][] cache;
public byte[] getData(int row, int col)
{
return cache[row][col];
}
public void updateData(int row, int col, byte[] data)
{
synchronized(cache)
{
if (!Arrays.equals(data,cache[row][col]))
{
cache[row][col] = data;
// Volatile write.
// The below line is intentional to ensure a volatile write is
// made to the array, since access via getData is unsynchronized.
this.cache = this.cache;
// Notification code removed
// (mentioning it since it is the reason for synchronizing).
}
}
}
Senza sincronizzazione, ritengo che sia tecnicamente necessaria la scrittura volatili assegnazione sé (anche se le bandiere IDE come avere alcun effetto). Con il blocco sincronizzato, penso che sia ancora necessario (dal momento che la lettura non è sincronizzata), ma voglio solo confermarlo poiché appare ridicolo nel codice se non è effettivamente richiesto. Non sono sicuro se ci sono garanzie che non sono a conoscenza tra la fine di un blocco sincronizzato e una lettura volatile.
Grazie per la risposta, è chiaro e conferma ciò che sospettavo. Anche il consiglio di avere due variabili di cache è probabilmente una buona idea poiché evita che qualcuno rimuova l'auto assegnazione (nonostante i commenti avvertano di non farlo). –