Вопрос относительно 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 помечает ее как не имеющую эффекта). С синхронизированным блоком я думаю, что это все еще необходимо (поскольку чтение не синхронизировано), но я просто хочу подтвердить, так как это выглядит нелепо в коде, если это на самом деле не требуется. Я не уверен, есть ли какие-либо гарантии, о которых я не знаю между концом синхронизированного блока и изменчивым чтением.