Question concernant le JMM et la sémantique des champs volatiles qui sont écrits dans un bloc synchronisé, mais lus de manière non synchronisée.
Dans une première version du code ci-dessous, je ne synchronisais pas les accès car cela n'était pas nécessaire pour les besoins antérieurs (et l'utilisation abusive d'une auto-assignation this.cache = this.cache garantissait une sémantique d'écriture volatile). Certaines exigences ont changé, nécessitant une synchronisation pour s'assurer que des mises à jour en double ne sont pas envoyées. La question que je me pose est la suivante : le bloc de synchronisation empêche-t-il d'exiger l'auto-assignation du champ 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).
}
}
}
Sans synchronisation, je pense que l'écriture volatile par auto-assignation est techniquement nécessaire (bien que l'IDE la signale comme n'ayant aucun effet). Avec le bloc synchronisé, je pense qu'elle est toujours nécessaire (puisque la lecture est non synchronisée), mais je veux juste confirmer car cela semble ridicule dans le code si elle n'est pas réellement nécessaire. Je ne suis pas sûr qu'il y ait des garanties que je ne connais pas entre la fin d'un bloc synchronisé et une lecture volatile.