Вопрос, касающийся JMM и семантики, касающихся изменчивых полей, которые записываются в синхронизированном блоке, но читаются несинхронизированно.
В начальной версии приведенного ниже кода я не выполнял синхронизацию доступа, поскольку в этом не было необходимости для более ранних требований (а злоупотребление самоназначением this.cache = this.cache обеспечивало изменчивую семантику записи). Некоторые требования изменились, и возникла необходимость в синхронизации, чтобы не рассылать повторяющиеся обновления. У меня возникает вопрос, не препятствует ли блок синхронизации требовать самоназначения изменчивого поля?
// 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).
}
}
}
Я считаю, что без синхронизации самоназначение изменчивой записи технически необходимо (хотя IDE помечает это как не имеющее эффекта). Я думаю, что с синхронизированным блоком он все еще необходим (поскольку чтение не синхронизировано), но я просто хочу подтвердить, поскольку это выглядит нелепо в коде, если он на самом деле не требуется. Я не уверен, есть ли какие-либо гарантии, о которых я не знаю, между концом синхронизированного блока и изменчивым чтением.