Достаточно ли простой записи внутри синхронизированного блока для возможной видимости getOpaque()?JAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Достаточно ли простой записи внутри синхронизированного блока для возможной видимости getOpaque()?

Сообщение Anonymous »

Использование режимов порядка памяти JDK 9, автор Дуг Ли:

Непрозрачный режим, полученный с помощью VarHandle getOpaque и setOpaque, добавляет ограничения по сравнению с обычным режимом, которые обеспечивают минимальную осведомленность о переменной, к которой осуществляется межпоточный доступ, когда все обращения используют непрозрачный (или более сильный) режим
[...]
Режим Release/Acquire (или RA) получается с помощью VarHandle setRelease, getAcquire и связанных с ним методов и добавляет «кумулятивное» ограничение причинности к непрозрачному режиму.

У нас в основном однопоточный путь кода, критичный к производительности. Мы хотим предоставить внутренний размер коллекции метрик (для Grafana), которые собираются другим потоком. Значение метрики не обязательно должно быть абсолютно актуальным — оно просто должно со временем стать видимым.
Чтобы избежать накладных расходов на изменчивые поля или синхронизированное чтение, мы используем подобную оболочку:

Код: Выделить всё

public class FastSizeMetric {

private long size;

private static final VarHandle SIZE_HANDLE;

static {
try {
SIZE_HANDLE = MethodHandles.lookup()
.findVarHandle(FastSizeMetric.class, "size", long.class);
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}

// must be used while holding a lock (any lock/synchronized block will do it)
public void updateSize(final long newSize) {
size = newSize; // plain write
}

public long getSize() {
return (long) SIZE_HANDLE.getOpaque(this);
}
}
Показатель всегда обновляется при сохранении какой-либо несвязанной блокировки:

Код: Выделить всё

    synchronized (jobId-related lock) {
// ... calculations ...
metric.updateSize(map.size());
// ... calculations ...
metric.updateSize(map.size());
// ... calculations ...
}
Поток сборщика метрик периодически вызывает getSize() с использованием getOpaque().
Вопросы:
  • Дает ли выполнение простой записи внутри синхронизированного блока те же гарантии конечной видимости для другого потока, вызывающего getOpaque(), что и явный setOpaque()?
  • Является ли "случайный" синхронизированный блок вокруг записи, достаточный для обеспечения возможной видимости непрозрачного чтения?
  • Гарантируется ли такое поведение спецификацией Java Memory Model / VarHandle, или это просто деталь реализации, которая работает в текущих JDK?
  • Можно ли на этот шаблон положиться в будущих версиях JDK, или нам действительно «повезет» сегодня?
TL;DR: является ли простая запись, защищенная синхронизацией + непрозрачное чтение, допустимым и перспективным шаблоном для метрик с низкой точностью, или нам следует явно использовать setOpaque() (или более сильный вариант)?>

Подробнее здесь: https://stackoverflow.com/questions/798 ... visibility
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»