Необходимость записи энергозависимого массива в синхронизированном блоке

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

8
задан Trevor Freeman 11 January 2012 в 22:43
поделиться